Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Problemas de conversion de código de x32 a x64 (https://www.clubdelphi.com/foros/showthread.php?t=94677)

aguml 20-05-2020 00:04:15

Problemas de conversion de código de x32 a x64
 
Buenas amigos, a parte de que algunas funciones de Windows ahora necesiten wchar_t* en vez de char* y int64_t en lugar de int, me encuentro con algunos problemas más que no sé cómo salvar. El primero es la estructura CONTEXT la cual contiene información de un proceso como los flags y registros, en x64 no me la reconoce ¿Sabéis cual es su equivalente para x64?
Otro es el DWORD que he visto que tiene que ser DWORD64 pero no sé si eso existe en c++builder o tiene que ser uint64_t o algo así.

ecfisa 20-05-2020 05:43:33

Hola.

Revisa si el siguiente enlace te ayuda en algo: 64-bit Windows Data Types Compared to 32-bit Windows Data Types

Saludos :)

aguml 20-05-2020 10:43:06

Gracias, me está sirviendo de ayuda aunque esto va para largo ya que una vez me compile tendré que revisar todo y ver como funciona cada cosa y estudiar como funcionan en x64 porque hay muchas que seguramente no coincidan con el funcionamiento de x32.
Tengo ahora mismo tres problemas/dudas:
1-No se que pasa con el tipo CONTEXT que si hago por ejemplo
Código PHP:

CONTEXT con;
con

el único método que sale es operator= y no aparecen ni los registros, ni flags ni nada de esa estructura. Estuve viendo que por internet decian que era por no tener el SDK y no lo tenia porque al instalarlo desde el instalador de RAD 10.3 Rio me daba error diciendo que no se podía conectar a internet o algo así por lo que me lo descargué directamente de Microsoft y lo añadí desde Tools->Options...->Deployment->SDK Manager y no tuve problemas al hacerlo pero sigo teniendo el mismo problema de que no puedo trabajar con el contenido de la estructura CONTEXT. He hecho clic derecho sobre CONTEXT y buscado su declaración y me sale en winnt.h toda la estructura pero sin embargo no puedo usarla T.T
Código PHP:

typedef struct DECLSPEC_ALIGN(16_CONTEXT {

    
//
    // Register parameter home addresses.
    //
    // N.B. These fields are for convience - they could be used to extend the
    //      context record in the future.
    //

    
DWORD64 P1Home;
    
DWORD64 P2Home;
    
DWORD64 P3Home;
    
DWORD64 P4Home;
    
DWORD64 P5Home;
    
DWORD64 P6Home;

    
//
    // Control flags.
    //

    
DWORD ContextFlags;
    
DWORD MxCsr;

    
//
    // Segment Registers and processor flags.
    //

    
WORD   SegCs;
    
WORD   SegDs;
    
WORD   SegEs;
    
WORD   SegFs;
    
WORD   SegGs;
    
WORD   SegSs;
    
DWORD EFlags;

    
//
    // Debug registers
    //

    
DWORD64 Dr0;
    
DWORD64 Dr1;
    
DWORD64 Dr2;
    
DWORD64 Dr3;
    
DWORD64 Dr6;
    
DWORD64 Dr7;

    
//
    // Integer registers.
    //

    
DWORD64 Rax;
    
DWORD64 Rcx;
    
DWORD64 Rdx;
    
DWORD64 Rbx;
    
DWORD64 Rsp;
    
DWORD64 Rbp;
    
DWORD64 Rsi;
    
DWORD64 Rdi;
    
DWORD64 R8;
    
DWORD64 R9;
    
DWORD64 R10;
    
DWORD64 R11;
    
DWORD64 R12;
    
DWORD64 R13;
    
DWORD64 R14;
    
DWORD64 R15;

    
//
    // Program counter.
    //

    
DWORD64 Rip;

    
//
    // Floating point state.
    //

    
union {
        
XMM_SAVE_AREA32 FltSave;
        
struct {
            
M128A Header[2];
            
M128A Legacy[8];
            
M128A Xmm0;
            
M128A Xmm1;
            
M128A Xmm2;
            
M128A Xmm3;
            
M128A Xmm4;
            
M128A Xmm5;
            
M128A Xmm6;
            
M128A Xmm7;
            
M128A Xmm8;
            
M128A Xmm9;
            
M128A Xmm10;
            
M128A Xmm11;
            
M128A Xmm12;
            
M128A Xmm13;
            
M128A Xmm14;
            
M128A Xmm15;
        } 
DUMMYSTRUCTNAME;
    } 
DUMMYUNIONNAME;

    
//
    // Vector registers.
    //

    
M128A VectorRegister[26];
    
DWORD64 VectorControl;

    
//
    // Special debug control registers.
    //

    
DWORD64 DebugControl;
    
DWORD64 LastBranchToRip;
    
DWORD64 LastBranchFromRip;
    
DWORD64 LastExceptionToRip;
    
DWORD64 LastExceptionFromRip;
CONTEXT, *PCONTEXT

2-Tengo varios TList los cuales uso para guardar cosas como datos de DLLs, BPs, HBPs... los cuales cuando ya no lo necesito tengo que liberar toda esa memoria y en x32 lo tenia así:
Código PHP:

delete ListaBPs->Items[pos];
ListaBPs->Delete(pos); 

En la primera linea, donde intento liberar la memoria del item, me da el siguiente Warning:
Código:

[bcc64 Warning] THiloDebugger.cpp(1839): cannot delete expression with pointer-to-'void' type 'void *'
No se si tengo que preocuparme o no por esa advertencia.

3-No me acepta la estructura __try catch(...), en su lugar he tenido que usar __try __except(EXCEPTION_EXECUTE_HANDLER)
¿hay alguna diferencia entre uno y otro? y por otro lado ¿que diferencia hay entre __try catch(...) y try catch(...)?
Ahora mismo los tengo así:
Código PHP:

void __fastcall TAntiAntiDebug::DeactiveInvalidHandle(bool estado)
{
        
__try{
                if(
HiloDepuracion != NULL)
                        
HiloDepuracion->DeactiveInvalidHandle(estado);
        }
__except(EXCEPTION_EXECUTE_HANDLER){
        }


Pero no se si con un try catch(...) bastaría.

aguml 20-05-2020 16:02:36

Pues pasa algo raro, aunque al poner el punto no me ofrece ninguno de los miembros que forman parte de la estructura, si lo pongo yo si lo acepta así que guiándome de esa estructura estoy corrigiendo todo lo que pueda pero en algunos puntos me veo que no puedo porque no se para que son algunos de ellos y a que equivalían en x32 para modificar sus respectivos métodos de x32 y convertirlos a x64.
Por ejemplo:
Código PHP:

void THiloDebugger::SetEAX(DWORD Valor)
{
        
con.Eax Valor;


Quedó así:
Código PHP:

void THiloDebugger::SetRAX(DWORD64 Valor)
{
        
con.Rax Valor;


Las de los Flags,Drx (los de los Hardware Breakpoints), ContextFlags, los SegXs no hay problema porque coinciden con los de x32.
Del resto no tengo ni idea de para que son y como leerlos y escribirlos y que utilidad podría tener leerlos o escribirlos.

aguml 20-05-2020 22:52:29

He conseguido encontrar info por la red y he reajustado todo para que me lea los registros de x64 (o eso creo porque eso está aun por ver) pero ahora tengo un problema y es que en el de x32 usaba EnumProcessModules para cuando me atacheo a un proceso poder saber las dlls que tenia cargadas el proceso y al cambiar a x64 vi que en la msdn dice que hay que usar EnumProcessModulesEx y el problema que tengo es que me da un error sobre la libreria psapi.lib:
Cita:

[ilink64 Error] Fatal: Invalid object file 'C:\USERS\AGUSTIN\DESKTOP\PROYECTO TDEBUGGER CON C++BUILDER 10.3 RIO X64\CLASE TDEBUGGER\PSAPI.LIB'
En x32 no fallaba esa libreria :confused:
¿Alguna idea?

aguml 21-05-2020 09:01:28

Arreglado eso también. lo tenía como:
Código PHP:

#pragma comment(lib,"psapi.lib") 

y lo dejé como:
Código PHP:

#pragma comment(lib,"psapi") 

por lo que he podido leer, en x64 se usan las librerías con extensión .a y no .lib y por eso me daba el problema. Poniéndolo como lo tengo ahora he leído que elige la que mejor se adapta, o sea que es mas portable.
Ahora mismo ya compila y me queda lo mas duro, comprobar todo y reparar fallos.

aguml 21-05-2020 16:41:25

Ahora tengo otro problema, no me lee el CONTEXT. Lo tengo asi:
Código PHP:

CONTEXT con;
...
...
...
con.ContextFlagsCONTEXT_FULL CONTEXT_FLOATING_POINT CONTEXT_DEBUG_REGISTERS;
if(
GetThreadContext(CurrentExceptionThread, &con)==0){
    
ShowMessage(WideString().sprintf(L"Error: %i",GetLastError()));
    
salir=true;


Y me muestra el error 998 que según la lista es ERROR_NOACCESS. ¿Que hago mal para que no me funcione? :confused:
Para crear el proceso lo tengo así:
Código PHP:

STARTUPINFO si;
PROCESS_INFORMATION pi;
...
...
si.cb sizeof(STARTUPINFO);
GetStartupInfo(&si);
CreateProcess(PathFile.c_bstr(),NULLNULLNULLFALSEDEBUG_PROCESS DEBUG_ONLY_THIS_PROCESSNULLNULL, &si, &pi); 


aguml 21-05-2020 21:52:58

He visto un poco el código de Titán enginer y veo que inicializa de forma diferente CONTEXT:
Código PHP:

DBGContext.ContextFlags CONTEXT_ALL CONTEXT_FLOATING_POINT CONTEXT_EXTENDED_REGISTERS

Y para crear el proceso lo hace así:
Código PHP:

__declspec(dllexportvoidTITCALL InitDebugW(wchar_tszFileNamewchar_tszCommandLinewchar_tszCurrentFolder)
{
    
int DebugConsoleFlag NULL;

    if(
DebugDebuggingDLL)
    {
        
DebugConsoleFlag CREATE_NO_WINDOW CREATE_SUSPENDED;
    }
    else if(
engineRemoveConsoleForDebugee)
    {
        
DebugConsoleFlag CREATE_NO_WINDOW;
    }

    if(
engineEnableDebugPrivilege)
    {
        
EngineSetDebugPrivilege(GetCurrentProcess(), true);
        
DebugRemoveDebugPrivilege true;
    }
    
wchar_tszFileNameCreateProcess;
    
wchar_tszCommandLineCreateProcess;
    
std::wstring createWithCmdLine;
    if(
szCommandLine == NULL || !lstrlenW(szCommandLine))
    {
        
szCommandLineCreateProcess 0;
        
szFileNameCreateProcess szFileName;
    }
    else
    {
        
createWithCmdLine.push_back('\"');
        
createWithCmdLine.append(szFileName);
        
createWithCmdLine.push_back('\"');
        
createWithCmdLine.push_back(' ');
        
createWithCmdLine.append(szCommandLine);
        
szCommandLineCreateProcess = (wchar_t*)createWithCmdLine.c_str();
        
szFileNameCreateProcess 0;
    }
    if(
CreateProcessW(szFileNameCreateProcessszCommandLineCreateProcessNULLNULLfalseDEBUG_PROCESS DEBUG_ONLY_THIS_PROCESS DebugConsoleFlag CREATE_NEW_CONSOLENULLszCurrentFolder, &dbgStartupInfo, &dbgProcessInformation))
    {
        if(
engineEnableDebugPrivilege)
            
EngineSetDebugPrivilege(GetCurrentProcess(), false);
        
DebugAttachedToProcess false;
        
DebugAttachedProcessCallBack NULL;
        return &
dbgProcessInformation;
    }
    else
    {
        
DWORD lastError GetLastError();
        if(
engineEnableDebugPrivilege)
        {
            
EngineSetDebugPrivilege(GetCurrentProcess(), false);
            
DebugRemoveDebugPrivilege false;
        }
        
memset(&dbgProcessInformation0sizeof(PROCESS_INFORMATION));
        
SetLastError(lastError);
        return 
0;
    }


Veo que le da o le quita privilegios justo después de crear el proceso.

aguml 21-05-2020 22:23:18

Veo que tanto para enviar cómo leer el context suspende antes el thread y después lo revive:
Código PHP:

    if(SuspendThread(hActiveThread) == (DWORD) - 1)
        return 
false;

    
returnf _GetFullContextDataEx(hActiveThreadtitcontexttrue);

    
ResumeThread(hActiveThread); 

Podría ser por eso que me deniegue el acceso ¿verdad?

aguml 23-05-2020 00:54:24

Bueno, después de mucho investigar he conseguido aprender cómo configurar el proyecto para que se lance como administrador y así poder obtener privilegios de depurador después y he estado haciendo pruebas y buscando información sobre el context. Sé que tiene que alinearse a 16 bytes y en winnt.h tengo esto:

Código PHP:

typedef struct DECLSPEC_ALIGN(16_CONTEXT {
...
... 

Yo después declaro así:
CONTEXT con;
¿Tengo que hacer algo más para que esté bien alineada? A todas las personas que le pasó era por el tema de la alineación de la estructura pero o eran en otro lenguaje o no especifican como arreglaron esto.

aguml 23-05-2020 11:16:51

He mirado en winnt como define DECLSPEC_ALIGN(n) y vi esto:

Código PHP:

#ifndef DECLSPEC_ALIGN
#if (_MSC_VER >= 1300) && !defined(MIDL_PASS) && !defined(__CODEGEARC__)
#define DECLSPEC_ALIGN(x)   __declspec(align(x))
#elif defined(__clang__) && !defined(MIDL_PASS)
#define DECLSPEC_ALIGN(x)   __attribute__((aligned(x)))
#else
#define DECLSPEC_ALIGN(x)
#endif
#endif 

Así que para probar si el problema podía venir por ahí he hecho esto antes de usar la cabecera winnt.h:

Código PHP:

#ifndef THiloDebuggerH
#define THiloDebuggerH
//---------------------------------------------------------------------------

#ifdef DECLSPEC_ALIGN
    #undef DECLSPEC_ALIGN
#endif
#define DECLSPEC_ALIGN
#define DECLSPEC_ALIGN(x)   __declspec(align(x))

#include <Classes.hpp>
#include <winnt.h>
#include <SyncObjs.hpp> 

Pero aun con esto me sigue dando el mismo error :(. Ya no se que mas mirar :confused:
Entonces coloqué el siguiente codigo antes de la cabecera de winnt.h:

Código PHP:

#if (_MSC_VER >= 1300) && !defined(MIDL_PASS) && !defined(__CODEGEARC__)
#define VALOR 1
#elif defined(__clang__) && !defined(MIDL_PASS)
#define VALOR 2
#else
#define VALOR 3
#endif 

Y mi sorpresa es que me muestra el 2 aunque yo lo haya definido antes así que hice esto:

Código PHP:

#define _MSC_VER 1300
#undef MIDL_PASS
#undef __CODEGEARC__ 

Y ahora me muestra el 1 pero ni así consigo librarme del error 998.

Necesito vuestra ayuda :p

aguml 23-05-2020 11:45:07

Perdón pero me di cuenta que el compilador me lanzaba Warnings y vi que estaba redefiniendo la constante así que la dejé así:
Código PHP:

#ifdef DECLSPEC_ALIGN
    #undef DECLSPEC_ALIGN
#endif
#define DECLSPEC_ALIGN(x)   __declspec(align(x)) 

Ya no me da Warnings pero sigue dando el mismo error 998 :(

aguml 24-05-2020 07:38:54

Al final di con el problema. El código era el de x86 y lo estaba adaptando a x64, pues bien, la dichosa estructura en x86 tiene que estar alineada a 8 bytes y para ello antes de la declaración de la clase había un pragma pack(push,8) y al final estaba su respectivo pragma pop con lo que quitando ambas ya fubciona y me deja depurar y ahora toca ir viendo los fallos que vayan saliendo.


La franja horaria es GMT +2. Ahora son las 19:46:05.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi