improvements to debug output for syscalls
This commit is contained in:
parent
33e05f058c
commit
8273da4ada
160
Debug.cpp
160
Debug.cpp
|
@ -14,9 +14,14 @@
|
|||
|
||||
#include "Debug.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include <filesystem>
|
||||
#include <cstdio>
|
||||
#include <syscall.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#define BUFFER_SIZE 128
|
||||
|
||||
|
@ -29,6 +34,7 @@ namespace krikkel
|
|||
using std::time;
|
||||
using std::localtime;
|
||||
using std::strftime;
|
||||
using std::min;
|
||||
|
||||
Debug::Debug()
|
||||
{
|
||||
|
@ -87,6 +93,160 @@ namespace krikkel
|
|||
logFile.flush();
|
||||
}
|
||||
|
||||
std::string Debug::peekData(pid_t shellPid, void *data, size_t length)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
for(int index = 0; index < length / sizeof(long); ++index)
|
||||
{
|
||||
long datum = ptrace(PTRACE_PEEKDATA, shellPid, ((char *) data) + index * sizeof(long));
|
||||
if(length == -1)
|
||||
{
|
||||
size_t datumLength = strnlen((char *) &datum, sizeof(long));
|
||||
result += string((char *) &datum, datumLength);
|
||||
if(datumLength < sizeof(long))
|
||||
break;
|
||||
}
|
||||
else
|
||||
result += string((char *) &datum, sizeof(long));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string Debug::formatToAddress(unsigned long long address)
|
||||
{
|
||||
char addressString[17];
|
||||
|
||||
snprintf(addressString, 17, "%016llx", address);
|
||||
|
||||
return string("0x") + addressString;
|
||||
}
|
||||
|
||||
void Debug::logPtraceSysCall(pid_t shellPid, uint16_t sysCallId, bool returnedFromSysCall, unsigned long long result, unsigned long long firstArgument, unsigned long long secondArgument, unsigned long long thirdArgument, unsigned long long fourthArgument, std::string fileName, int lineNo, std::string functionName)
|
||||
{
|
||||
const static uint8_t maxStringLength = 32;
|
||||
string message = "syscall: ";
|
||||
|
||||
string sysCallName;
|
||||
if(sysCallId < MAX_NUMBER_OF_SYSCALLS)
|
||||
sysCallName = syscalls[sysCallId];
|
||||
if(sysCallName.empty())
|
||||
sysCallName = "syscall" + std::to_string(sysCallId);
|
||||
|
||||
|
||||
switch(sysCallId)
|
||||
{
|
||||
case SYS_read:
|
||||
if(returnedFromSysCall)
|
||||
message += (result == -1 ? "-1" : std::to_string((size_t) result)) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ", \"" + (returnedFromSysCall ? __debug_make_bytes_printable(peekData(shellPid, (char *) secondArgument, (size_t) min<unsigned long long>(thirdArgument, maxStringLength))) : "")
|
||||
+ (maxStringLength < thirdArgument || returnedFromSysCall == true ? "[…]" : "") + "\""
|
||||
+ ", " + std::to_string((size_t) thirdArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_write:
|
||||
if(returnedFromSysCall)
|
||||
message += (result == -1 ? "-1" : std::to_string((size_t) result)) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ", \"" + __debug_make_bytes_printable(peekData(shellPid, (char *) secondArgument, (size_t) min<unsigned long long>(thirdArgument, maxStringLength)))
|
||||
+ (maxStringLength < thirdArgument || returnedFromSysCall == true ? "[…]" : "") + "\""
|
||||
+ ", " + std::to_string((size_t) thirdArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_close:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_stat:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(\"" + peekData(shellPid, (char *) firstArgument, -1) + "\""
|
||||
+ ", " + formatToAddress(secondArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_fstat:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ", " + formatToAddress(secondArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_openat:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + ((int) firstArgument == AT_FDCWD ? string("AT_FDCWD") : std::to_string((int) firstArgument))
|
||||
+ ", \"" + __debug_make_bytes_printable(peekData(shellPid, (char *) secondArgument, -1)) + "\""
|
||||
+ ", " + std::to_string((int) thirdArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_rt_sigprocmask:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ", " + formatToAddress(secondArgument)
|
||||
+ ", " + formatToAddress(thirdArgument)
|
||||
+ ", " + std::to_string((size_t) fourthArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_access:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + peekData(shellPid, (char *) firstArgument, -1)
|
||||
+ ", " + std::to_string((int) secondArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_dup2:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ", " + std::to_string((int) secondArgument)
|
||||
+ ")";
|
||||
break;
|
||||
case SYS_fcntl:
|
||||
if(returnedFromSysCall)
|
||||
message += std::to_string((int) result) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + std::to_string((int) firstArgument)
|
||||
+ ", " + (secondArgument == 0 ? string("F_DUP_FD") : std::to_string((int) secondArgument))
|
||||
+ ", …"
|
||||
+ ")";
|
||||
break;
|
||||
/* case SYS_fstat:
|
||||
struct stat statbuf;
|
||||
message += "(" + std::to_string(firstArgument)
|
||||
+ ", \"" + __debug_make_bytes_printable(peekData(shellPid, (char *) secondArgument, (size_t) min<unsigned long long>(thirdArgument, maxStringLength)))
|
||||
+ (maxStringLength < thirdArgument ? "[…]" : "") + "\""
|
||||
+ ", " + std::to_string((size_t) thirdArgument)
|
||||
+ ")";
|
||||
break;
|
||||
*/ default:
|
||||
if(returnedFromSysCall)
|
||||
message += (result == -1 ? "-1" : std::to_string(result)) + " = ";
|
||||
message += sysCallName
|
||||
+ "(" + formatToAddress(firstArgument)
|
||||
+ ", " + formatToAddress(secondArgument)
|
||||
+ ", " + formatToAddress(thirdArgument)
|
||||
+ ", " + formatToAddress(fourthArgument)
|
||||
+ ")";
|
||||
}
|
||||
// source: https://blog.rchapman.org/posts/Linux_System_Call_Table_for_x86_64/
|
||||
|
||||
log(message, fileName, lineNo, functionName);
|
||||
}
|
||||
|
||||
Debug *Debug::getInstance()
|
||||
{
|
||||
static Debug *debug = new Debug();
|
||||
|
|
11
Debug.hpp
11
Debug.hpp
|
@ -26,17 +26,22 @@ namespace krikkel
|
|||
Debug();
|
||||
std::string getTimestamp();
|
||||
std::string getUname();
|
||||
std::string peekData(pid_t shellPid, void *data, size_t length);
|
||||
std::string formatToAddress(unsigned long long address);
|
||||
|
||||
public:
|
||||
void log(std::string message, std::string fileName, int lineNo
|
||||
, std::string functionName);
|
||||
void logPtraceSysCall(pid_t shellPid, uint16_t sysCallId, bool returnedFromSysCall, unsigned long long result, unsigned long long firstArgument, unsigned long long secondArgument, unsigned long long thirdArgument, unsigned long long fourthArgument, std::string fileName, int lineNo, std::string functionName);
|
||||
static Debug *getInstance();
|
||||
};
|
||||
}
|
||||
|
||||
#define __debug_log(message) krikkel::Debug::getInstance()\
|
||||
->log(message, __FILE__, __LINE__, __func__)
|
||||
#define __debug_log(message) \
|
||||
krikkel::Debug::getInstance()->log(message, __FILE__, __LINE__, __func__)
|
||||
|
||||
#define __debug_log_ptrace_syscall(shellPid, sysCallId, returnedFromSysCall, result, firstArgument, secondArgument, thirdArgument, fourthArgument) \
|
||||
krikkel::Debug::getInstance()->logPtraceSysCall(shellPid, sysCallId, returnedFromSysCall, result, firstArgument, secondArgument, thirdArgument, fourthArgument, __FILE__, __LINE__, __func__);
|
||||
|
||||
/// @todo need an explanation on why and how to use this
|
||||
/// this is the complete opposite of self-explanatory
|
||||
|
@ -104,7 +109,7 @@ namespace krikkel
|
|||
if(std::isprint(character, loc) && character != '<') \
|
||||
result += character; \
|
||||
else \
|
||||
result += '<' + std::to_string(character) + '>'; \
|
||||
result += '<' + std::to_string((unsigned char) character) + '>'; \
|
||||
} \
|
||||
return result; \
|
||||
})(__bytes)
|
||||
|
|
Loading…
Reference in a new issue