Global variable/direct reference works, local variable doesn't - format (y_va)
#1

So, it all started with my server crashing when using y_va from YSI 4. The simple solution is - don't use it, but I love YSI, and want to make it better (but I seem to pesky for ****** and often get ignored. Such is life).
I narrowed the problem to simple testcase: http://pastebin.com/CfNnWUj2 - run this with crashdetect enabled, and YSI from YSI.tl branch (manual amx_assembly download might be required). If you don't get a crash, please write your specs. Any help appreciated.


Also: can someone explain to me what is @emit (used by asm.inc from amx_assembly)? I don't grasp what it is. It generates native assembly of #emit opcodes?
Reply
#2

Hangover bump. I'd like at least if someone could simply confirm that happens to them as well.
Reply
#3

I don't ignore people, I'm just very busy - I haven't touched 4.0 code in weeks because of other priorities!

For information on @emit, see these links:

Early library that modifies itself.
More self-modifying code.
How to modify code on Linux.
Library to simplify it.
Macro for syntactic sugar.

There isn't much documentation on using "asm.inc", it's for run-time code modification. "@emit" is just shorthand for the main functions to look like "#emit".
Reply
#4

Thanks for the links, ****** showed only @emit one. Zeex writes awesome stuff, but with zero commentary.

Back to y_va: I dumped the stack right before sysreq:
Quote:

16
16528
64
8
28
79
0
0
0
0

Quote:

24
16236
64
96
144
168
196
79
0
0

For Fun and NoFun:
pawn Код:
Fun(str, sizeof str, "HI%s", "Folks");
NoFun(str, sizeof str, "Hello%s%s%s", "Folks", "JOKERS", "Temporary");
Then I tried to get the string passed as first parameter (16528 and 16236). The Fun string got echoed correctly, but the second one:
Quote:

[20:03:54] [debug] Run time error 5: "Invalid memory access"
[20:03:54] [debug] AMX backtrace:
[20:03:54] [debug] #0 00000318 in va_format (out[]=@0x00003f6c "Used to be", size=64, fmat[]=@0x00000060 "Hello%s%s%s", va_:STATIC_ARGS=3) at D:\Programming\Pawn\NSSRP\gamemodes\dickbutt.pwn:8 6
[20:03:54] [debug] #1 00000214 in NoFun (out[]=@0x00000318 "", size=64, fmat[]=@0x00000060 "Hello%s%s%s", ... <4049 arguments>) at D:\Programming\Pawn\NSSRP\gamemodes\dickbutt.pwn:3 4
[20:03:54] [debug] #2 00000120 in main () at D:\Programming\Pawn\NSSRP\gamemodes\dickbutt.pwn:2 4
[20:03:54] Script[gamemodes/dickbutt.amx]: Run time error 5: "Invalid memory access"

0x00003f6c == 16236

Does it have anything to do with STK pointer manipulation done earlier?

Any help welcome, I'm tinkering 2 days now.

#e: Minor dent:
pawn Код:
#emit PUSH.S       fmat
#emit PUSH.S       size
#emit PUSH         16256
#emit PUSH         YSI_g_sArgCount // Push the parameter count.

#emit SYSREQ.C     format
Works as intended. 16256 is address of str from previous frame. Now I have some direction, but still a little clueless
Reply
#5

If I run the code I get the message the format itself crashed therefore it is unrelated to va_format

format simple crashes if the output address is out of range like
pawn Код:
NotFine(out[], size, const fmt[], va_args<>) {
    format(killer, sizeof killer, fmt, ...);

    new
        killer[128]
    ;
}
Test code
pawn Код:
main() {
    static
        addr,
        array[] = "Hello World"
    ;
    format(array, sizeof array, array);

    const
        size = sizeof array,
        byte = size * -4
    ;
    // Calculating address of tmp
    #emit lctrl 4 // stack
    #emit add.c byte
    #emit stor.pri addr

//  new tmp[sizeof array]; // works

    #emit push.c array
    #emit push.c size
    #emit push addr
    #emit push.c 12
    #emit sysreq.c format
    #emit stack 16

    new tmp[sizeof array]; // doesn't

    print(tmp);
}
Reply
#6

Just a thought: Can you use a static local variable in the interim? They are technically globals so won't crash, but have the scope of locals.
Reply
#7

Static variable work flawless but the strange thing is that I saw plenty of function posted here with used a local variable in va_format

I never used y_va before so I can't tell if it is just a problem with the current sa-mp version or not
Reply
#8

Quote:

format itself crashed therefore it is unrelated to va_format

My understanding is that in moment of moving stack pointer up, it accidentally overwrites more than just few parameters, causing overwriting of local variables (below frame pointer of next function call). No idea if I got that right, but maybe the variable was moved to YSI_g_sArgs all along.

Thanks for confirming!
Reply
#9

I'll have a look - I did recently rewrite y_va to what I thought was a faster method, but may have been a worse method...
Reply
#10

Ok, so I have an idea - simply move the stack pointer -(number of variable arguments * 4), then use MOVS/memcpy to copy the variable arguments from previous frame (without touching the frame pointer), and standard pushing of remaining args. I'm not sure though if it will be any faster than YSI 3 version with standard while + it requires runtime rewriting of MOVS (which I suck at, even when using amx_assembly).
Reply
#11

MOVS requires that the source and destination areas don't overlap, which they would for any more than about 2 parameters.
Reply
#12

How? I thought it would be like:

Before
Quote:

12345 //Previous frame
123 //Return address of function 1
20 //Number of arguments
4 //Argument 1
8 //Argument 2 - first variable argument
12 // Argument 3
16 // Argument 4
20 // Argument 5 - last variable argument, set PRI to point here
128 //Local variable in function 2
12346 //Frame of function 2
123 //Return address of function 2
4 //Number of arguments
4
0
0
0
0 //We force STK and ALT to point here

Now we call movs with 16 bytes (4 variable arguments).
After:
Quote:

12345
123
20
4
8
12
16
20
128
12346
123
4
4
8
12
16
20 //STK still points here

I missed something?
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)