Raised This Month: $100 Target: $400
 25% 

[INC] valist.inc Variable arguments function


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Kailo
Senior Member
Join Date: Sep 2014
Location: Moscow, Russia
Old 08-12-2017 , 11:46   [INC] valist.inc Variable arguments function
Reply With Quote #1

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
Attached Files
File Type: inc valist.inc (2.5 KB, 6 views)

Last edited by Kailo; 12-11-2017 at 07:12.
Kailo is offline
Deathknife
Senior Member
Join Date: Aug 2014
Old 08-13-2017 , 14:27   Re: [INC] valist.inc Variable arguments function
Reply With Quote #2

This is awesome!
__________________
Deathknife is offline
zipcore
Veteran Member
Join Date: Mar 2010
Location: m_flZipcore
Old 08-14-2017 , 07:37   Re: [INC] valist.inc Variable arguments function
Reply With Quote #3

Yay n1
__________________
zipcore is offline
Kailo
Senior Member
Join Date: Sep 2014
Location: Moscow, Russia
Old 09-11-2017 , 03:21   Re: [INC] valist.inc Variable arguments function
Reply With Quote #4

Not working in 1.9 since sourcepawn "Disallow negative indices in all array access patterns" (d7743c3) update.

Last edited by Kailo; 12-09-2017 at 13:44.
Kailo is offline
Kailo
Senior Member
Join Date: Sep 2014
Location: Moscow, Russia
Old 12-09-2017 , 16:27   Re: [INC] valist.inc Variable arguments function
Reply With Quote #5

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.

Last edited by Kailo; 12-09-2017 at 16:47.
Kailo is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 18:28.


Powered by vBulletin®
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Theme made by Freecode