Pelles C forum
C language => Expert questions => Topic started by: Seltsamuel on June 23, 2008, 10:40:36 PM
-
Hi,
I found a strange Behavior in Pelles C and i dont know a workaround for now.
Here is my Problem:
//Typedef of a later used Datatable
typedef struct
{
DWORD Address;
DWORD Value;
} Patch;
first i declared a Data Table:
unsigned char Table_Test[]=
{
0xCA,0x00,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFA,0x00,0x00,0x00,0x0C,0x00,0x00,0x00
};
then i make another Table:
static Patch TestPatch[] =
{
{(DWORD) Table_Test,0}
};
all i get is this: #2069: Initializer must be constant.
in Visual Studio and gcc this works fine.
The same Problem occurs when i want to get the adress of an already written function into the Table
like this:
static Patch TestPatch2[] =
{
{(DWORD) MyFunc,0}
};
again: Initializer must be constant.
i dont get it because i can use fine:
myfunc2(&Myfunc)
I dont know the Reason for this Error because it makes no sense.
Any Help is appreciated because i already tried all possible combinations i know to go around it.
Greetings
Seltsamuel
-
This behaviour is due to limitation imposed by C99 to global and static struct/union initialization.
For more info's google "static init struct c99".
Anyway you can workaround the problem using the new C99 feature "designated initializers" as follows:
typedef struct
{
union
{
unsigned char *PhAddress;
DWORD Address;
};
DWORD Value;
} Patch;
unsigned char Table_Test[]=
{
0xCA,0x00,0x00,0x00,0xC0,0xFF,0xFF,0xFF,0xFA,0x00,0x00,0x00,0x0C,0x00,0x00,0x00
};
static Patch TestPatch[] =
{
{.PhAddress=Table_Test, .Value=0}
};
Where you can use the form:
.<element name> = <value>
-
Hi,
many thanks i will try this.
Nevertheless i see not the Reason why they did it in c99 becaue it only makes code less readable.
is there a possibility to switch pelles C to an older standard ? Compatible with behavior of gcc or Vc++ ?
I have another Question this Time its Assembly:
I need to Jump to external references that i know are there how can i make this best?
Dont try to understand the code its only a collection of instructions and makes no sense ^^
#define NAKED void __declspec(naked)
NAKED Test(void)
{
__asm
{
mov ecx,[0x6f4a4fc1] <- This works nowhere declared not referenced nothing
call 0x6f4a4fc1 <- this works not "Relocation expression is too complex"
jmp 0x6f4a4fc1 <- same here
ret
};
};
how can i make that it works? i know the destination exists where i want to jump to because i validate that the dll is loaded at its preferred base. So it must not be relocatable. I dont want to use a local Jumptable like i do now to circumvent this problem it should be a direct jump or call like in my example.
Is there somewhere a dokumentation for Pelles C inline Assembly ? what i found here at the board and inside the Manual was not really exhausting helpfull. I will be happy about a complete documentation.
Many thanks in advance
Seltsamuel
-
is there a possibility to switch pelles C to an older standard ? Compatible with behavior of gcc or Vc++ ?
Old standards, i.e. C89 or C90, are even more restrictive, so maybe you have to wait for C2010 ;)
gcc and VC permits this kind of initialization as ustom extensions, if you use the C99 switch they will not be allowed anymore.
I need to Jump to external references that i know are there how can i make this best?
The symbol table generator has difficulties to generate absolute references, like yours, in jmp and call instructions. Use indirect addressing as showed below.
NAKED Test(void)
{
__asm
{
mov ecx,0x6f4a4fc1
call [ecx] //call indirect
jmp [ecx] //jump indirect
ret
};
};
-
Hi,
many thx frankie,
the indirect way im going at the Moment but this way:
typedef void (_stdcall *naked_call)(void);
naked_call Testdestination = (naked_call)0x33677411;
void __declspec(naked) Testpatch1(void)
{
__asm
{
jmp Testdestination
};
};
this generates a jmp [Testdestination]
Ugly nevertheless but uses no additional Opcodes and eats no additional Registers.
Im doing Game Modding on Assembly level so i modify executable Code at Runtime implanting
Jumps to my own Code inside my DLL and route it Back. The Problem is i have to reference many
Global Variables and Functions of the foreign Code. Runtime Gamemodding is in my oppinion one of the
hardest Tasks to accomplish. And because the use of inline Assembly is vital to the Task i would greatly appreciate a link to the complete Dokumentation of Pelles C inline assembler.
Thanks
Seltsamuel
-
Seltsamuel,
unfortunately X86 assembler doesn't have any jmp or call near absolute adressing form. To code an absolute near address you *only have the indirect addressing mode*. This means use memory, as you are doing, or a register, as you don't like.
PellesC assembler resemble the MASM assembler, so you can use one of the many tutorials for masm available on the net. The whole Poasm documentation available is in the help file that come with PellesC suite.
If you want a major control on the assembler generated code use NASM, that is probably more direct to handle 'glue' code between different modules.
-
Hi,
thanks for your answer.
unfortunately X86 assembler doesn't have any jmp or call near absolute adressing form.
Hi, yes i know Jumps in flat memory are always relative but the statement in itself is not really true.
What i want IS possible and i can explain how :-) but Pelles C isnt able to do it.
When Pelles C Compiles the file he can calculate the address to the absolute address and put it to the relocation table! so the system itself would modify it to fit during loading time (the destination is assured not to move!) so technically absolutely possible and not different to this mov ecx,[0x6f4a4fc1]
At the Moment im starting to get comfortable with Pelles C and i only can say good work and well done!
For the little things not working as expected i have working workarounds so no Problem at all :-)
Many thanks for your help frankie!
PS: Your workaround for the Structs is really working.
Greetings
Seltsamuel
-
When Pelles C Compiles the file he can calculate the address to the absolute address and put it to the relocation table! so the system itself would modify it to fit during loading time (the destination is assured not to move!) so technically absolutely possible and not different to this mov ecx,[0x6f4a4fc1]
It is completely different from the form using indirect register addressing because the address in the register *is an absolute address*, while the value following the cal opcode *is an offset* from address of instruction following the call to the requested address.
Moreover the real problem is not the object relocation table, but the PE format that doesn't allow the linking with a relative-but-absolute reference outside the module section (I kind of catch22 where for a relative addressing of the instruction a fake absolute address must be generated).
Anyway something like this may work (I've not tried it)
db 0xA9 ;the call opcode, or it is 0xE9 I don't remember. Check on Intel docs
dd 0x33677411-$+5 ;the 5 is the next instruction address
EDIT: Doesn't work! Even NASM gives error to build the relocation table for M$-Coff format (obj).
-
Hi,
i feared this, anyway thanks for trying :-)
So i have to resolve this problem with building this Instructions during runtime lika a runtime Assembler does.
Greetings
Seltsamuel