//
// Public API of jtrace for third parties
//  
// License: Absolutely free for NON-COMMERCIAL use. 
// 
// If you want to use this commercially, Please talk to me. 
// 
// You might want to consider reading my books, or going
// to a training at www.technologeeks.com, where we teach 
// this stuff and lots more.
//
//
#include <sys/types.h>
#include <sys/socket.h>

#ifndef JTRACE_API_H
#define JTRACE_API_H

//
// New, far simpler API:
//
// No more regs! Registers are stashed in thread local storage and entirely abstracted by getRegValue(#)
// so you don't need to concern yourself with arch differences. Also, is_32() gets bitness from TLS as well,
// so getRegValue needs just one argument - the register number!
//


int ignoreAllSyscalls(void);


uint32_t hexDumpToBuffer (char *OutputBuf, int OutputLen, char *Buffer, int Len, uint64_t Address, int Indent);

#ifndef _32
typedef unsigned long uint64_t;
#endif

#ifdef _32
#define arch_int uint32_t
#else

#define arch_int uint64_t
#endif


//
// Abstracting the calling convention:
//
// JTrace will automatically translate these register "numbers" into the corresponding
// registers of the underlying architecture, as per the ABI. In the ARM64 case, these
// are straightforward noops - ARG_0...ARG_7 are X0..X7. In ARM32, X0..X3 are 0..3,
// but jtrace is smart enough to get the other "register" values from the stack. In the
// Intel case, the mapping is between rdi/rsi/rdx/rcx/r8/r9 or the stack.
//
// Likewise, the syscall number - in Intel, that's eax/rax. In ARM32/ARM64 r7/r8 respectively
//
// This enables you to get the arguments in a plugin without bothering to consider how the 
// calling convention works!

#define REG_ARG_0	0
#define REG_ARG_1	1
#define REG_ARG_2	2
#define REG_ARG_3	3
#define REG_ARG_4	4 // ARM32: stack
#define REG_ARG_5	5
#define REG_ARG_6	6 // Probably won't need more than this since syscalls have max 6..
#define REG_ARG_7	7

// these are intentionally values greater than ARM64's registers,
// so we are guaranteed to map them by ABI
#define REG_ARG_RETVAL		33
#define REG_ARG_SYSCALL_NUM	34

// The actual register representation is the per architecture pt_regs,
// but that's made opaque by this here struct
typedef struct jtregs regs_t;

// the opaque structure will be provided for you (by reference) when jtrace
// calls your callback handler, which needs to be implemented as:

typedef enum {
	DO_NOTHING = 0, // You want JTrace to continue as normal
	BLOCK 	   = 1, // You want JTrace to block this system call
	NOT_HANDLED = 2, // You didn't handle the syscall
} syscall_handler_ret_t;

typedef syscall_handler_ret_t (*syscall_handler_func) (int exit, int pid);

enum syscallHandlerFlags {
	
	HANDLER_ENTRY_ONLY = 1,
	HANDLER_EXIT_ONLY  = 2,
	HANDLER_OVERRIDE_DEFAULT = 1024,
};

// piece de resistance
int registerSyscallHandler (char *SyscallName, // must exist or you'll get -1 
	     syscall_handler_func Handler,     // Your callback, per above
		              int Bitness,     // 32, 64 or 0 (both)
			      int Flags);      // as per flags, above

#define ERR_SYSCALL_NOT_FOUND	(-1)

// The idea is to then leave the regs_t opaque, and use the accessor:
// And to ensure that's the case, JTrace no longer exports regs.
long getRegValue (int num);

// setRegValue - calls GETREGS, changes your value, then calls SETREGS

void setRegValue (int num, uint64_t value);


// Stash register values between calls. 
// Use this primarily for REG_ARG_0, which will be often destroyed
// on syscall exit. Note the saved registers are also on TLS, but
// may be different from the "real" ones (i.e. getRegValue ! necessarily = getSavedRegValue)
//
void saveRegValue (uint32_t Reg) ;
uint64_t getSavedRegValue (uint32_t Reg);


// This conveniently hides process_vm_readv, /proc/pid/mem, or ptrace
int readProcessMemory (int Pid, arch_int Addr, int Size, char *MyAddr);

//--- 3/30/2017 ----

// And this can set the process memory, writing Size bytes from MyAddr to Addr!
int writeProcessMemory (int Pid, arch_int Addr, int Size, char *MyAddr);

// Get an FD name. This is useful for operating in read/write hooks only
// if the fd is connected to a certain file
char *getFDName(int fd);


//--- 3/26/2018 One year later --

typedef int binderHook_t (char *Parcel , size_t Size, int Code);

int registerBinderIoctlHook(char *interface, // UTF-8 or UTF-16 OK
			    binderHook_t	Hook);
			


// -- 3/07/2020 Two years further: Back to Android Internals, full steam!

// Returns jtrace verbosity level, as per user specified "-v" arguments.
// You can use this to have your plugin print more (or less) information accordingly
int getVerbosityLevel ();

char *getIOVecDataFromMsgHdr (struct msghdr *MsgHdr,
			      unsigned int *BytesRead,
			      pid_t    Pid);


// Resolve name (from cmdline) for a given PID.
// hides /proc/<pid>/cmdline, and possible caching
char *getProcNameForPid (pid_t pid);

// Is JTrace's current config colorful?

int config_color() ;
int config_debug() ;
//--------------------------------------------------------------------

// Other APIs I use for testing
//-----------------------------

// Get a system call number by providing its name. This is especially useful
// for testing, because God only knows why the numbers keep changing across
// various platforms.

int getSyscallNum (char *);

//  New - Rather than printf()
char *getOutputBuffer ();
void updateOutputBufferPos(int byHowMuch);






// For testing
void dumpArgumentsForSyscall (char *);
void dumpAllSyscalls(int); 



int get_is32(void);
#endif
