Blame src/object/mdso_objgen_symfn.c

97d39b
/****************************************************************/
97d39b
/*  mdso: midipix dso scavenger                                 */
97d39b
/*  Copyright (C) 2015--2017  Z. Gilboa                         */
97d39b
/*  Released under GPLv2 and GPLv3; see COPYING.MDSO.           */
97d39b
/****************************************************************/
97d39b
97d39b
#include <stdio.h>
97d39b
#include <stddef.h>
97d39b
#include <stdint.h>
97d39b
#include <stdlib.h>
97d39b
#include <string.h>
97d39b
97d39b
#include <mdso/mdso.h>
97d39b
#include "mdso_object_impl.h"
97d39b
#include "mdso_errinfo_impl.h"
97d39b
#include "perk_consts.h"
97d39b
#include "perk_structs.h"
97d39b
97d39b
static const unsigned char jmp_code_i386[16] = {
97d39b
	0xff,0x25,
97d39b
	0x0,0x0,0x0,0x0,
97d39b
	0x90,0x90,
97d39b
	0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0
97d39b
};
97d39b
97d39b
static const unsigned char jmp_code_amd64[16] = {
97d39b
	0xff,0x24,0x25,
97d39b
	0x0,0x0,0x0,0x0,
97d39b
	0x90,
97d39b
	0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90
97d39b
};
97d39b
97d39b
struct mdso_symfn_code {
97d39b
	unsigned char 	code[16];
97d39b
};
97d39b
97d39b
struct mdso_symfn_object {
97d39b
	struct pe_raw_coff_object_hdr	hdr;
97d39b
	struct pe_raw_sec_hdr		sec[1];
97d39b
	struct mdso_symfn_code		cod[1];
97d39b
	struct pe_raw_coff_reloc	rel[1];
97d39b
	struct pe_raw_coff_symbol	sym[7];
97d39b
	struct pe_raw_coff_strtbl	cst;
97d39b
};
97d39b
97d39b
int mdso_objgen_symfn(
97d39b
	const struct mdso_driver_ctx *	dctx,
97d39b
	const char *			sym,
97d39b
	FILE *				fout,
97d39b
	struct mdso_object *		vobj)
97d39b
{
97d39b
	struct mdso_symfn_object *	symfn;
97d39b
	struct pe_raw_coff_symbol *	symrec;
97d39b
	const unsigned char *		code;
97d39b
	unsigned char *			mark;
97d39b
	struct pe_aux_rec_section *	aux;
97d39b
	size_t				buflen;
97d39b
	uint32_t			symlen;
97d39b
	uint32_t			cstlen;
97d39b
	uint32_t			objlen;
97d39b
	uint32_t			aattr;
97d39b
	uint32_t			sattr;
97d39b
	uint16_t			oattr;
97d39b
	uint16_t			machine;
97d39b
	uint16_t			reltype;
97d39b
	uint32_t			relrva;
97d39b
	uint32_t			reloff;
97d39b
	uint32_t			symoff;
97d39b
	uint32_t			cstoff;
97d39b
	uint32_t			codoff;
97d39b
	uint32_t			datoff;
97d39b
97d39b
	if ((buflen = strlen(sym)) > 1024*1024)
97d39b
		return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA);
97d39b
97d39b
	symlen = (uint32_t)buflen;
97d39b
	cstlen = (3 * symlen) + 32;
97d39b
	objlen = sizeof(*symfn) + cstlen;
97d39b
97d39b
	if (vobj && vobj->addr && (vobj->size < objlen))
97d39b
		return MDSO_BUFFER_ERROR(dctx);
97d39b
97d39b
	if (vobj && !vobj->addr) {
97d39b
		vobj->size = objlen;
97d39b
		return 0;
97d39b
	}
97d39b
97d39b
	if (vobj)
97d39b
		symfn = (struct mdso_symfn_object *)vobj->addr;
97d39b
97d39b
	else if (!(symfn = calloc(1,objlen)))
97d39b
		return MDSO_SYSTEM_ERROR(dctx);
97d39b
97d39b
	if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) {
97d39b
		code    = jmp_code_amd64;
97d39b
		aattr   = PE_IMAGE_SCN_ALIGN_16BYTES;
97d39b
		machine = PE_IMAGE_FILE_MACHINE_AMD64;
97d39b
		reltype = PE_IMAGE_REL_AMD64_ADDR32;
97d39b
		relrva  = 3;
97d39b
	} else {
97d39b
		code    = jmp_code_i386;
97d39b
		aattr   = PE_IMAGE_SCN_ALIGN_4BYTES;
97d39b
		machine = PE_IMAGE_FILE_MACHINE_I386;
97d39b
		reltype = PE_IMAGE_REL_I386_DIR32;
97d39b
		relrva  = 2;
97d39b
	}
97d39b
97d39b
	sattr  = aattr;
97d39b
	sattr |= PE_IMAGE_SCN_MEM_READ;
97d39b
	sattr |= PE_IMAGE_SCN_MEM_EXECUTE;
97d39b
	sattr |= PE_IMAGE_SCN_CNT_CODE;
97d39b
97d39b
	oattr  = PE_IMAGE_FILE_LINE_NUMS_STRIPPED;
97d39b
	reloff = offsetof(struct mdso_symfn_object,rel);
97d39b
	symoff = offsetof(struct mdso_symfn_object,sym);
97d39b
	codoff = offsetof(struct mdso_symfn_object,cod);
97d39b
	cstoff = offsetof(struct pe_raw_coff_strtbl,cst_data);
97d39b
	datoff = 0;
97d39b
97d39b
	/* coff object header */
97d39b
	mdso_obj_write_short(symfn->hdr.cfh_machine,machine);
97d39b
	mdso_obj_write_short(symfn->hdr.cfh_num_of_sections,1);
97d39b
	mdso_obj_write_long(symfn->hdr.cfh_ptr_to_sym_tbl,symoff);
97d39b
	mdso_obj_write_long(symfn->hdr.cfh_num_of_syms,7);
97d39b
	mdso_obj_write_short(symfn->hdr.cfh_characteristics,oattr);
97d39b
97d39b
	/* .text section header */
97d39b
	memcpy(symfn->sec[0].sh_name,".text",5);
97d39b
	mdso_obj_write_long(symfn->sec[0].sh_size_of_raw_data,16);
97d39b
	mdso_obj_write_long(symfn->sec[0].sh_ptr_to_raw_data,codoff);
97d39b
	mdso_obj_write_long(symfn->sec[0].sh_ptr_to_relocs,reloff);
97d39b
	mdso_obj_write_short(symfn->sec[0].sh_num_of_relocs,1);
97d39b
	mdso_obj_write_long(symfn->sec[0].sh_characteristics,sattr);
97d39b
97d39b
	/* .text section content */
97d39b
	memcpy(symfn->cod,code,16);
97d39b
97d39b
	/* .text relocation record */
97d39b
	mdso_obj_write_long(symfn->rel[0].rel_sym,6);
97d39b
	mdso_obj_write_long(symfn->rel[0].rel_rva,relrva);
97d39b
	mdso_obj_write_short(symfn->rel[0].rel_type,reltype);
97d39b
97d39b
	/* coff string table */
97d39b
	mdso_obj_write_long(symfn->cst.cst_size,cstlen);
97d39b
97d39b
	/* coff symbol table */
97d39b
	symrec = symfn->sym;
97d39b
	mark   = symfn->cst.cst_data;
97d39b
97d39b
	/* coff symbol: .file */
97d39b
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_FILE;
97d39b
	symrec[0].cs_num_of_aux_symbols[0] = 1;
97d39b
97d39b
	mdso_obj_write_short(&symrec[0].cs_section_number[0],PE_IMAGE_SYM_DEBUG);
97d39b
	mdso_obj_write_long(&symrec[1].cs_name[4],cstoff+datoff);
97d39b
97d39b
	memcpy(symrec[0].cs_name,".file",5);
97d39b
	memcpy(&mark[0],"__",2);
97d39b
	memcpy(&mark[2],sym,symlen);
97d39b
	memcpy(&mark[2+symlen],"_sym_fn.s",9);
97d39b
97d39b
	datoff += 12 + symlen;
97d39b
	mark   += 12 + symlen;
97d39b
	symrec += 2;
97d39b
97d39b
	/* coff symbol: .text */
97d39b
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
97d39b
	symrec[0].cs_num_of_aux_symbols[0] = 1;
97d39b
97d39b
	mdso_obj_write_short(symrec[0].cs_section_number,1);
97d39b
	memcpy(symrec[0].cs_name,".text",5);
97d39b
97d39b
	aux = (struct pe_aux_rec_section *)&symrec[1];
97d39b
	mdso_obj_write_long(aux->aux_size,relrva+4);
97d39b
	mdso_obj_write_short(aux->aux_num_of_relocs,1);
97d39b
97d39b
	datoff += 0;
97d39b
	mark   += 0;
97d39b
	symrec += 2;
97d39b
97d39b
	/* coff symbol: sym */
97d39b
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL;
97d39b
	symrec[0].cs_num_of_aux_symbols[0] = 1;
97d39b
97d39b
	mdso_obj_write_short(symrec[0].cs_type,PE_IMAGE_SYM_DTYPE_FUNCTION<<8);
97d39b
	mdso_obj_write_short(symrec[0].cs_section_number,1);
97d39b
	mdso_obj_write_long(&symrec[0].cs_name[4],cstoff+datoff);
97d39b
97d39b
	if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) {
97d39b
		memcpy(&mark[0],sym,symlen);
97d39b
	} else {
97d39b
		memcpy(&mark[1],sym,symlen);
97d39b
		mark[0] = '_';
97d39b
		datoff++;
97d39b
		mark++;
97d39b
	}
97d39b
97d39b
	datoff += 1 + symlen;
97d39b
	mark   += 1 + symlen;
97d39b
	symrec += 2;
97d39b
97d39b
	/* coff symbol: __imp_sym */
97d39b
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL;
97d39b
	symrec[0].cs_num_of_aux_symbols[0] = 0;
97d39b
97d39b
	mdso_obj_write_short(symrec[0].cs_section_number,0);
97d39b
	mdso_obj_write_long(&symrec[0].cs_name[4],cstoff+datoff);
97d39b
97d39b
	if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) {
97d39b
		memcpy(&mark[0],"__imp_",6);
97d39b
		memcpy(&mark[6],sym,symlen);
97d39b
	} else {
97d39b
		memcpy(&mark[0],"__imp_",6);
97d39b
		memcpy(&mark[7],sym,symlen);
97d39b
		mark[6] = '_';
97d39b
		datoff++;
97d39b
		mark++;
97d39b
	}
97d39b
97d39b
	/* tada */
97d39b
	if (fout)
97d39b
		if (fwrite(symfn,objlen,1,fout) == 0)
97d39b
			return MDSO_FILE_ERROR(dctx);
97d39b
97d39b
	return 0;
97d39b
}