diff --git a/buildlib.bat b/buildlib.bat new file mode 100644 index 0000000..9397441 --- /dev/null +++ b/buildlib.bat @@ -0,0 +1 @@ +clang++ -D DEBUG src\tmrtsc.hpp -Wall -Wextra -Wpedantic -std=c++11 -g -gcodeview -Wl,-pdb= -L C:\capybara\libclang\x86_64-w64-mingw32\bin -l c++ -l unwind --verbose diff --git a/src/tmrtsc.hpp b/src/tmrtsc.hpp index 6ff7632..051e85c 100644 --- a/src/tmrtsc.hpp +++ b/src/tmrtsc.hpp @@ -1,10 +1,7 @@ //TODO It's threadin' time #ifdef _WIN64 - //TODO mirame esta - #ifndef DEBUG - #define DEBUG - #endif + #define LIB_EXPORT __declspec(dllexport) #define UNICODE #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT _WIN32_WINNT_WIN10 //0x0A00 @@ -14,47 +11,105 @@ #include #include #include +#else + #define LIB_EXPORT #endif + #include #include #include "debug.h" +/* + * #if _WIN64 + * extern "C" {) + * #endif + */ namespace tmr { #ifdef _WIN64 - enum winReturnValues{ + enum LIB_EXPORT winReturnValues{ CANT_OPEN_KEY = -1, CANT_RETRIEVE_KEY_INFO = -2, CANT_READ_DATA_FROM_VALUE = -3, CANT_RETRIEVE_FREQUENCY = -4 }; #endif - enum ReturnValues { + enum LIB_EXPORT ReturnValues { OPERATION_SUCCESSFUL = 0, - INVARIANT_TSC_NOT_AVAILABLE = -1, + INVARIANT_TSC_NOT_SUPPORTED = -1, UNSUPPORTED_CPU = -2, CANT_READ_FREQUENCY_FROM_SYSTEM = -3, ART_NOT_REPORTED = -4 }; - class TSCTimer { + class LIB_EXPORT TSCTimer { private: static TSCTimer timer; - static char* vendorName; - static int64_t baseFreq = ART_NOT_REPORTED; - + + char* vendorName; + int64_t baseFreq = ART_NOT_REPORTED; bool availableRDTSCP; int64_t art; //reserved - TSCtimer () { + TSCTimer (char* vendorName, int64_t baseFreq) { + this->vendorName = vendorName; + this->baseFreq = baseFreq; availableRDTSCP = (checkRDTSCP()) ? true : false; - } + } + ~TSCTimer () { + free(vendorName); + } + + static bool checkInvariantTSC() { + uint64_t rdx; + asm volatile (".intel_syntax noprefix\t\n" \ + "mov eax, 0x80000007\t\n" \ + "cpuid\t\n" : "=d" (rdx) ); + bool iTSC = rdx & (1<<8); + return iTSC; + } + + + static char* readVendorName () { + char* palabritas = (char*)malloc(sizeof(char) * 13); + uint8_t siguienteLetra = 0; + uint64_t regs[3]; + asm volatile ( ".intel_syntax noprefix\t\n" \ + "mov eax, 0x0\t\n" \ + "cpuid\t\n" : "=b" (regs[0]), "=c" (regs[2]), "=d" (regs[1]) ); + int byte = 0; + for (int reg = 0; reg < 3; reg++, byte = 0){ + char* charifiedReg = (char*)®s[reg]; + for(; byte < 4; byte++, siguienteLetra++ ){ + palabritas[siguienteLetra] = charifiedReg[byte]; + } + } + palabritas[siguienteLetra] = '\0'; + return palabritas; + } + + static int64_t intelRetrieveART(){ + //TODO: Find a valid Intel CPU to debug ART route + //if (freq == nullptr) return - + + uint64_t raxde, rbxnum, rcxhz; + asm volatile ( ".intel_syntax noprefix\t\n" \ + "mov eax, 0x15\t\n" \ + "cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) ); + log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz); + if (rbxnum == 0 || rcxhz == 0) return ART_NOT_REPORTED; + int64_t TSCFreq = (rcxhz * rbxnum)/raxde; + //*freq = TSCFreq; + log_debugcpp("raxo " << TSCFreq << " " << TSCFreq); + return TSCFreq; + } + #ifdef _WIN64 - int64_t getFreqFromSystem(){ + static int64_t getFreqFromSystem(){ //TODO: close opened key const WORD STRING_SIZE = 4; const WCHAR COMPARE_TARGET[STRING_SIZE + 1] = L"~MHz"; @@ -129,15 +184,6 @@ namespace tmr { #endif - bool checkInvariantTSC() { - uint64_t rdx; - asm volatile (".intel_syntax noprefix\t\n" \ - "mov eax, 0x80000007\t\n" \ - "cpuid\t\n" : "=d" (rdx) ); - bool iTSC = rdx & (1<<8); - return iTSC; - } - bool checkRDTSCP(){ //Generic uint64_t rdx; asm volatile (".intel_syntax noprefix\t\n" \ @@ -149,40 +195,6 @@ namespace tmr { return RDTSCP; } - char* readVendorName () { - char* palabritas = (char*)malloc(sizeof(char) * 13); - uint8_t siguienteLetra = 0; - uint64_t regs[3]; - asm volatile ( ".intel_syntax noprefix\t\n" \ - "mov eax, 0x0\t\n" \ - "cpuid\t\n" : "=b" (regs[0]), "=c" (regs[2]), "=d" (regs[1]) ); - int byte = 0; - for (int reg = 0; reg < 3; reg++, byte = 0){ - char* charifiedReg = (char*)®s[reg]; - for(; byte < 4; byte++, siguienteLetra++ ){ - palabritas[siguienteLetra] = charifiedReg[byte]; - } - } - palabritas[siguienteLetra] = '\0'; - return palabritas; - } - - int64_t intelCheckART(){ - //TODO: Find a valid Intel CPU to debug ART route - //if (freq == nullptr) return - - - uint64_t rbxnum, rcxhz; - asm volatile ( ".intel_syntax noprefix\t\n" \ - "mov eax, 0x15\t\n" \ - "cpuid\t\n" : "=a" (raxde), "=b" (rbxnum), "=c" (rcxhz) ); - log_debugcpp("hmm " << raxde << " " << rbxnum << " " << rcxhz); - if (rbxnum == 0 || rcxhz == 0) return ART_NOT_REPORTED; - int64_t TSCFreq = (rcxhz * rbxnum)/raxde; - //*freq = TSCFreq; - log_debugcpp("raxo " << TSCFreq << " " << *freq); - return TSCFreq; - } - uint64_t readRDTSC() { uint64_t raxlo,rdxho; asm volatile ( ".intel_syntax noprefix\t\n" @@ -203,13 +215,14 @@ namespace tmr { public: static int getTimer(TSCTimer* timer = nullptr) { - if (!checkInvariantTSC) return INVARIANT_TSC_NOT_SUPPORTED; - + if (!checkInvariantTSC()) return INVARIANT_TSC_NOT_SUPPORTED; + //TODO debug dis const char vendorNames[2][13] = { - {"AuthenticAMD\0"}, - {"GenuineIntel\0"} + {"AuthenticAMD"}, + {"GenuineIntel"} }; - vendorName = readVendorName(); + char* vendorName = readVendorName(); + int64_t baseFreq; if (strcmp(vendorName, vendorNames[1])) baseFreq = intelRetrieveART(); @@ -218,7 +231,7 @@ namespace tmr { if (baseFreq < OPERATION_SUCCESSFUL) return CANT_READ_FREQUENCY_FROM_SYSTEM; - timer = new TSCTimer(); + timer = new TSCTimer(vendorName, baseFreq); return OPERATION_SUCCESSFUL; } @@ -228,6 +241,16 @@ namespace tmr { else return readRDTSC(); } + + uint64_t getBaseFrequency(){ + return baseFreq; + } + }; - } } + +/* + * #ifdef _WIN64 + * } + * #endif + */