Fix ptrace bug on 64bit linux systems

develop
Petr Mrázek 2010-04-27 00:12:22 +02:00
parent 157deb85af
commit 41268470b6
12 changed files with 289 additions and 73 deletions

@ -81,7 +81,13 @@ SET( MEMXML_DATA_PATH . CACHE PATH "search path for Memory.xml")
# OPTION( VARIABLE "Description" Initial state)
#OPTION( WITH_FOO "Enable FOO support" ON )
#OPTION( WITH_BAR "Enable BAR component" OFF )
# Are we 64bit? (Damn you, ptrace()!)
IF( CMAKE_SIZEOF_VOID_P MATCHES 4 )
SET( HAVE_64_BIT 0 )
ELSE( CMAKE_SIZEOF_VOID_P MATCHES 4 )
SET( HAVE_64_BIT 1 )
ENDIF( CMAKE_SIZEOF_VOID_P MATCHES 4 )
CONFIGURE_FILE( ${CMAKE_SOURCE_DIR}/dfhack/config.h.cmake ${CMAKE_SOURCE_DIR}/dfhack/include/config.h )
@ -110,8 +116,8 @@ IF(UNIX)
install(FILES ${CMAKE_SOURCE_DIR}/output/Memory.xml DESTINATION share/dfhack)
ENDIF(UNIX)
# SWIG stuff
FIND_PACKAGE(SWIG)
# SWIG stuff is dead
# FIND_PACKAGE(SWIG)
#IF(SWIG_FOUND)
# INCLUDE(${SWIG_USE_FILE})

@ -704,6 +704,25 @@ void SHMProcess::readDWord (const uint32_t offset, uint32_t &val)
val = D_SHMHDR->value;
}
uint64_t SHMProcess::readQuad (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_QUAD);
return D_SHMHDR->Qvalue;
}
void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
gcc_barrier
d->SetAndWait(CORE_READ_QUAD);
val = D_SHMHDR->Qvalue;
}
float SHMProcess::readFloat (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
@ -727,6 +746,16 @@ void SHMProcess::readFloat (const uint32_t offset, float &val)
* WRITING
*/
void SHMProcess::writeQuad (const uint32_t offset, const uint64_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->Qvalue = data;
gcc_barrier
d->SetAndWait(CORE_WRITE_QUAD);
}
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();

@ -442,46 +442,93 @@ void WineProcess::readFloat (const uint32_t offset, float &val)
read(offset, 4, (uint8_t *) &val);
}
void WineProcess::readQuad (const uint32_t offset, uint64_t &val)
{
read(offset, 8, (uint8_t *) &val);
}
uint64_t WineProcess::readQuad (const uint32_t offset)
{
uint64_t val;
read(offset, 8, (uint8_t *) &val);
return val;
}
/*
* WRITING
*/
void WineProcess::writeQuad (uint32_t offset, const uint64_t data)
{
#ifdef HAVE_64_BIT
ptrace(PTRACE_POKEDATA,d->my_handle, offset, data);
#else
ptrace(PTRACE_POKEDATA,d->my_handle, offset, (uint32_t) data);
ptrace(PTRACE_POKEDATA,d->my_handle, offset+4, (uint32_t) (data >> 32));
#endif
}
void WineProcess::writeDWord (uint32_t offset, uint32_t data)
{
ptrace(PTRACE_POKEDATA,d->my_handle, offset, data);
#ifdef HAVE_64_BIT
uint64_t orig = readQuad(offset);
orig &= 0xFFFFFFFF00000000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#else
ptrace(PTRACE_POKEDATA,d->my_handle, offset, data);
#endif
}
// using these is expensive.
void WineProcess::writeWord (uint32_t offset, uint16_t data)
{
uint32_t orig = readDWord(offset);
/*;
uint16_t & zz = (uint16_t&) orig;
zz = data;
*/
orig &= 0xFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#ifdef HAVE_64_BIT
uint64_t orig = readQuad(offset);
orig &= 0xFFFFFFFFFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#else
uint32_t orig = readDWord(offset);
orig &= 0xFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#endif
}
void WineProcess::writeByte (uint32_t offset, uint8_t data)
{
uint32_t orig = readDWord(offset);
orig &= 0xFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#ifdef HAVE_64_BIT
uint64_t orig = readQuad(offset);
orig &= 0xFFFFFFFFFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#else
uint32_t orig = readDWord(offset);
orig &= 0xFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#endif
}
// blah. I hate the kernel devs for crippling /proc/PID/mem. THIS IS RIDICULOUS
void WineProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
{
printf("0x%x, size %d\n", source, size);
uint32_t count = 0;
uint32_t indexptr = 0;
while (size > 0)
{
#ifdef HAVE_64_BIT
// quad!
if(size >= 8)
{
writeQuad(offset, *(uint64_t *) (source + indexptr));
offset +=8;
indexptr +=8;
size -=8;
}
else
#endif
// default: we push 4 bytes
if(size >= 4)
{
@ -489,7 +536,6 @@ void WineProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
offset +=4;
indexptr +=4;
size -=4;
count +=4;
}
// last is either three or 2 bytes
else if(size >= 2)
@ -498,17 +544,14 @@ void WineProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
offset +=2;
indexptr +=2;
size -=2;
count +=2;
}
// finishing move
else if(size == 1)
{
writeByte(offset, *(uint8_t *) (source + indexptr));
count ++;
return;
}
}
printf("written %d\n", count);
}
const std::string WineProcess::readCString (uint32_t offset)

@ -428,46 +428,91 @@ void NormalProcess::readFloat (const uint32_t offset, float &val)
read(offset, 4, (uint8_t *) &val);
}
uint64_t NormalProcess::readQuad (const uint32_t offset)
{
uint64_t val;
read(offset, 8, (uint8_t *) &val);
return val;
}
void NormalProcess::readQuad (const uint32_t offset, uint64_t &val)
{
read(offset, 8, (uint8_t *) &val);
}
/*
* WRITING
*/
void NormalProcess::writeQuad (uint32_t offset, const uint64_t data)
{
#ifdef HAVE_64_BIT
ptrace(PTRACE_POKEDATA,d->my_handle, offset, data);
#else
ptrace(PTRACE_POKEDATA,d->my_handle, offset, (uint32_t) data);
ptrace(PTRACE_POKEDATA,d->my_handle, offset+4, (uint32_t) (data >> 32));
#endif
}
void NormalProcess::writeDWord (uint32_t offset, uint32_t data)
{
ptrace(PTRACE_POKEDATA,d->my_handle, offset, data);
#ifdef HAVE_64_BIT
uint64_t orig = readQuad(offset);
orig &= 0xFFFFFFFF00000000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#else
ptrace(PTRACE_POKEDATA,d->my_handle, offset, data);
#endif
}
// using these is expensive.
void NormalProcess::writeWord (uint32_t offset, uint16_t data)
{
uint32_t orig = readDWord(offset);
orig &= 0xFFFF0000;
orig |= data;
/*
orig |= 0x0000FFFF;
orig &= data;
*/
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#ifdef HAVE_64_BIT
uint64_t orig = readQuad(offset);
orig &= 0xFFFFFFFFFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#else
uint32_t orig = readDWord(offset);
orig &= 0xFFFF0000;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#endif
}
void NormalProcess::writeByte (uint32_t offset, uint8_t data)
{
uint32_t orig = readDWord(offset);
orig &= 0xFFFFFF00;
orig |= data;
/*
orig |= 0x000000FF;
orig &= data;
*/
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#ifdef HAVE_64_BIT
uint64_t orig = readQuad(offset);
orig &= 0xFFFFFFFFFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#else
uint32_t orig = readDWord(offset);
orig &= 0xFFFFFF00;
orig |= data;
ptrace(PTRACE_POKEDATA,d->my_handle, offset, orig);
#endif
}
// blah. I hate the kernel devs for crippling /proc/PID/mem. THIS IS RIDICULOUS
void NormalProcess::write (uint32_t offset, uint32_t size, uint8_t *source)
{
uint32_t count = 0;
uint32_t indexptr = 0;
while (size > 0)
{
#ifdef HAVE_64_BIT
// quad!
if(size >= 8)
{
writeQuad(offset, *(uint64_t *) (source + indexptr));
offset +=8;
indexptr +=8;
size -=8;
}
else
#endif
// default: we push 4 bytes
if(size >= 4)
{

@ -769,7 +769,7 @@ float SHMProcess::readFloat (const uint32_t offset)
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
return D_SHMHDR->value;
return (float) D_SHMHDR->value;
}
void SHMProcess::readFloat (const uint32_t offset, float &val)
{
@ -778,14 +778,42 @@ void SHMProcess::readFloat (const uint32_t offset, float &val)
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_DWORD);
val = D_SHMHDR->value;
val = (float) D_SHMHDR->value;
}
uint64_t SHMProcess::readQuad (const uint32_t offset)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_QUAD);
return D_SHMHDR->Qvalue;
}
void SHMProcess::readQuad (const uint32_t offset, uint64_t &val)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
full_barrier
d->SetAndWait(CORE_READ_QUAD);
val = D_SHMHDR->Qvalue;
}
/*
* WRITING
*/
void SHMProcess::writeQuad (uint32_t offset, uint64_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();
D_SHMHDR->address = offset;
D_SHMHDR->Qvalue = data;
full_barrier
d->SetAndWait(CORE_WRITE_QUAD);
}
void SHMProcess::writeDWord (uint32_t offset, uint32_t data)
{
if(!d->locked) throw Error::MemoryAccessDenied();

@ -365,6 +365,20 @@ void NormalProcess::readDWord (const uint32_t offset, uint32_t &result)
throw Error::MemoryAccessDenied();
}
uint64_t NormalProcess::readQuad (const uint32_t offset)
{
uint64_t result;
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint64_t), NULL))
throw Error::MemoryAccessDenied();
return result;
}
void NormalProcess::readQuad (const uint32_t offset, uint64_t &result)
{
if(!ReadProcessMemory(d->my_handle, (int*) offset, &result, sizeof(uint64_t), NULL))
throw Error::MemoryAccessDenied();
}
float NormalProcess::readFloat (const uint32_t offset)
{
float result;
@ -386,22 +400,28 @@ void NormalProcess::read (const uint32_t offset, uint32_t size, uint8_t *target)
}
// WRITING
void NormalProcess::writeQuad (const uint32_t offset, uint64_t data)
{
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(data), NULL))
throw Error::MemoryAccessDenied();
}
void NormalProcess::writeDWord (const uint32_t offset, uint32_t data)
{
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint32_t), NULL))
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(data), NULL))
throw Error::MemoryAccessDenied();
}
// using these is expensive.
void NormalProcess::writeWord (uint32_t offset, uint16_t data)
{
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint16_t), NULL))
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(data), NULL))
throw Error::MemoryAccessDenied();
}
void NormalProcess::writeByte (uint32_t offset, uint8_t data)
{
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(uint8_t), NULL))
if(!WriteProcessMemory(d->my_handle, (int*) offset, &data, sizeof(data), NULL))
throw Error::MemoryAccessDenied();
}

@ -2,5 +2,6 @@
#define CONFIG_H
#cmakedefine MEMXML_DATA_PATH @MEMXML_DATA_PATH@
#cmakedefine HAVE_64_BIT
#endif // CONFIG_H

@ -80,21 +80,28 @@ namespace DFHack
// force-resume DF execution
virtual bool forceresume() = 0;
virtual uint64_t readQuad(const uint32_t address) = 0;
virtual void readQuad(const uint32_t address, uint64_t & value) = 0;
virtual void writeQuad(const uint32_t address, const uint64_t value) = 0;
virtual uint32_t readDWord(const uint32_t address) = 0;
virtual float readFloat(const uint32_t address) = 0;
virtual void readDWord(const uint32_t address, uint32_t & value) = 0;
virtual void writeDWord(const uint32_t address, const uint32_t value) = 0;
virtual float readFloat(const uint32_t address) = 0;
virtual void readFloat(const uint32_t address, float & value) = 0;
virtual uint16_t readWord(const uint32_t address) = 0;
virtual void readWord(const uint32_t address, uint16_t & value) = 0;
virtual void writeWord(const uint32_t address, const uint16_t value) = 0;
virtual uint8_t readByte(const uint32_t address) = 0;
virtual void readByte(const uint32_t address, uint8_t & value) = 0;
virtual void read( uint32_t address, uint32_t length, uint8_t* buffer) = 0;
virtual void writeDWord(const uint32_t address, const uint32_t value) = 0;
virtual void writeWord(const uint32_t address, const uint16_t value) = 0;
virtual void writeByte(const uint32_t address, const uint8_t value) = 0;
virtual void read( uint32_t address, uint32_t length, uint8_t* buffer) = 0;
virtual void write(uint32_t address, uint32_t length, uint8_t* buffer) = 0;
// read a string
virtual const string readSTLString (uint32_t offset) = 0;
virtual size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity) = 0;
@ -151,21 +158,28 @@ namespace DFHack
bool resume();
bool forceresume();
uint64_t readQuad(const uint32_t address);
void readQuad(const uint32_t address, uint64_t & value);
void writeQuad(const uint32_t address, const uint64_t value);
uint32_t readDWord(const uint32_t address);
float readFloat(const uint32_t address);
void readDWord(const uint32_t address, uint32_t & value);
void writeDWord(const uint32_t address, const uint32_t value);
float readFloat(const uint32_t address);
void readFloat(const uint32_t address, float & value);
uint16_t readWord(const uint32_t address);
void readWord(const uint32_t address, uint16_t & value);
void writeWord(const uint32_t address, const uint16_t value);
uint8_t readByte(const uint32_t address);
void readByte(const uint32_t address, uint8_t & value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void writeDWord(const uint32_t address, const uint32_t value);
void writeWord(const uint32_t address, const uint16_t value);
void writeByte(const uint32_t address, const uint8_t value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const string readSTLString (uint32_t offset);
size_t readSTLString (uint32_t offset, char * buffer, size_t bufcapacity);
void writeSTLString(const uint32_t address, const std::string writeString){};
@ -216,19 +230,26 @@ namespace DFHack
bool resume();
bool forceresume();
uint64_t readQuad(const uint32_t address);
void readQuad(const uint32_t address, uint64_t & value);
void writeQuad(const uint32_t address, const uint64_t value);
uint32_t readDWord(const uint32_t address);
float readFloat(const uint32_t address);
void readDWord(const uint32_t address, uint32_t & value);
void writeDWord(const uint32_t address, const uint32_t value);
float readFloat(const uint32_t address);
void readFloat(const uint32_t address, float & value);
uint16_t readWord(const uint32_t address);
void readWord(const uint32_t address, uint16_t & value);
void writeWord(const uint32_t address, const uint16_t value);
uint8_t readByte(const uint32_t address);
void readByte(const uint32_t address, uint8_t & value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void writeDWord(const uint32_t address, const uint32_t value);
void writeWord(const uint32_t address, const uint16_t value);
void writeByte(const uint32_t address, const uint8_t value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const string readSTLString (uint32_t offset);
@ -280,19 +301,26 @@ namespace DFHack
bool resume();
bool forceresume();
uint64_t readQuad(const uint32_t address);
void readQuad(const uint32_t address, uint64_t & value);
void writeQuad(const uint32_t address, const uint64_t value);
uint32_t readDWord(const uint32_t address);
float readFloat(const uint32_t address);
void readDWord(const uint32_t address, uint32_t & value);
void writeDWord(const uint32_t address, const uint32_t value);
float readFloat(const uint32_t address);
void readFloat(const uint32_t address, float & value);
uint16_t readWord(const uint32_t address);
void readWord(const uint32_t address, uint16_t & value);
void writeWord(const uint32_t address, const uint16_t value);
uint8_t readByte(const uint32_t address);
void readByte(const uint32_t address, uint8_t & value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void writeDWord(const uint32_t address, const uint32_t value);
void writeWord(const uint32_t address, const uint16_t value);
void writeByte(const uint32_t address, const uint8_t value);
void read( uint32_t address, uint32_t length, uint8_t* buffer);
void write(uint32_t address, uint32_t length, uint8_t* buffer);
const string readSTLString (uint32_t offset);

@ -2,5 +2,6 @@
#define CONFIG_H
#define MEMXML_DATA_PATH .
#define HAVE_64_BIT
#endif // CONFIG_H

@ -60,6 +60,11 @@ void ReadRaw (void * data)
memcpy(SHMDATA(void), (void *) SHMHDR->address,SHMHDR->length);
}
void ReadQuad (void * data)
{
SHMHDR->Qvalue = *((uint64_t*) SHMHDR->address);
}
void ReadDWord (void * data)
{
SHMHDR->value = *((uint32_t*) SHMHDR->address);
@ -80,6 +85,11 @@ void WriteRaw (void * data)
memcpy((void *)SHMHDR->address, SHMDATA(void),SHMHDR->length);
}
void WriteQuad (void * data)
{
(*(uint64_t*)SHMHDR->address) = SHMHDR->Qvalue;
}
void WriteDWord (void * data)
{
(*(uint32_t*)SHMHDR->address) = SHMHDR->value;
@ -214,12 +224,14 @@ DFPP_module InitCore(void)
// raw reads
core.set_command(CORE_READ, FUNCTION,"Raw read",ReadRaw, CORE_SUSPENDED);
core.set_command(CORE_READ_QUAD, FUNCTION,"Read QUAD",ReadQuad, CORE_SUSPENDED);
core.set_command(CORE_READ_DWORD, FUNCTION,"Read DWORD",ReadDWord, CORE_SUSPENDED);
core.set_command(CORE_READ_WORD, FUNCTION,"Read WORD",ReadWord, CORE_SUSPENDED);
core.set_command(CORE_READ_BYTE, FUNCTION,"Read BYTE",ReadByte, CORE_SUSPENDED);
// raw writes
core.set_command(CORE_WRITE, FUNCTION, "Raw write", WriteRaw, CORE_SUSPENDED);
core.set_command(CORE_WRITE_QUAD, FUNCTION, "Write QUAD", WriteQuad, CORE_SUSPENDED);
core.set_command(CORE_WRITE_DWORD, FUNCTION, "Write DWORD", WriteDWord, CORE_SUSPENDED);
core.set_command(CORE_WRITE_WORD, FUNCTION, "Write WORD", WriteWord, CORE_SUSPENDED);
core.set_command(CORE_WRITE_BYTE, FUNCTION, "Write BYTE", WriteByte, CORE_SUSPENDED);

@ -26,7 +26,7 @@ distribution.
#define SHMS_CORE_H
// increment on every core change
#define CORE_VERSION 8
#define CORE_VERSION 10
typedef struct
{
@ -35,6 +35,7 @@ typedef struct
uint32_t value;
uint32_t length;
uint32_t error;
uint64_t Qvalue;
} shm_core_hdr;
typedef struct
@ -67,7 +68,7 @@ enum CORE_COMMAND
CORE_SUSPEND, // client notifies server to wait for commands (server is stalled in busy wait)
CORE_SUSPENDED, // response to WAIT, server is stalled in busy wait
CORE_ERROR, // there was a server error
// utility commands
CORE_ATTACH, // compare affinity, get core version and process ID
CORE_ACQUIRE_MODULE, // get index of a loaded module by name and version
@ -75,12 +76,14 @@ enum CORE_COMMAND
// raw reads
CORE_READ, // cl -> sv, read some data
CORE_READ_QUAD, // cl -> sv, read a quad
CORE_READ_DWORD, // cl -> sv, read a dword
CORE_READ_WORD, // cl -> sv, read a word
CORE_READ_BYTE, // cl -> sv, read a byte
// raw writes
CORE_WRITE,// client writes to server
CORE_WRITE_QUAD,// client writes a QUAD to server
CORE_WRITE_DWORD,// client writes a DWORD to server
CORE_WRITE_WORD,// client writes a WORD to server
CORE_WRITE_BYTE,// client writes a BYTE to server

@ -76,8 +76,8 @@ TARGET_LINK_LIBRARIES(dfcatsplosion dfhack)
IF(UNIX)
SET(CURSES_NEED_WIDE "YES")
SET(CURSES_NEED_NCURSES "YES")
find_package(Curses)
SET(CURSES_NEED_NCURSES "NO")
find_package(Curses QUIET)
IF(CURSES_FOUND)
if(CURSES_HAVE_NCURSESW_NCURSES_H)
@ -106,7 +106,7 @@ IF(UNIX)
)
ENDIF(NCURSES_H)
ELSE(CURSES_FOUND)
MESSAGE(STATUS "Wide-character ncurses library not found - vainlook can't be built")
MESSAGE(STATUS "Wide-character ncurses library not found - veinlook can't be built")
ENDIF(CURSES_FOUND)
ENDIF(UNIX)