Blame src/object/mdso_objgen_dsometa.c

2f0331
/****************************************************************/
2f0331
/*  mdso: midipix dso scavenger                                 */
2f0331
/*  Copyright (C) 2015--2017  Z. Gilboa                         */
2f0331
/*  Released under GPLv2 and GPLv3; see COPYING.MDSO.           */
2f0331
/****************************************************************/
2f0331
2f0331
#include <stdio.h>
2f0331
#include <stddef.h>
2f0331
#include <stdint.h>
2f0331
#include <stdlib.h>
2f0331
#include <string.h>
a3e2cf
#include <sys/mman.h>
2f0331
2f0331
#include <mdso/mdso.h>
2f0331
#include <mdso/mdso_specs.h>
2f0331
#include "mdso_object_impl.h"
2f0331
#include "mdso_errinfo_impl.h"
2f0331
#include "perk_consts.h"
2f0331
#include "perk_structs.h"
2f0331
2f0331
struct mdso_unified_record {
2f0331
	unsigned char 	data[80];
2f0331
};
2f0331
2f0331
struct mdso_dsometa_object {
2f0331
	struct pe_raw_coff_object_hdr	hdr;
2f0331
	struct pe_raw_sec_hdr		sec[2];
2f0331
	struct mdso_unified_record	rec[1];
2f0331
	struct pe_raw_coff_reloc	rel[1];
2f0331
	struct pe_raw_coff_symbol	sym[8];
2f0331
	struct pe_raw_coff_strtbl	cst;
2f0331
};
2f0331
2f0331
int mdso_objgen_dsometa(
2f0331
	const struct mdso_driver_ctx *	dctx,
2f0331
	struct mdso_object *		vobj)
2f0331
{
2f0331
	struct mdso_dsometa_object *	dsometa;
2f0331
	struct pe_raw_coff_symbol *	symrec;
a3e2cf
	void *				addr;
2f0331
	unsigned char *			mark;
bbf7fc
	struct pe_raw_aux_rec_section *	aux;
2f0331
	size_t				buflen;
2f0331
	uint32_t			liblen;
2f0331
	uint32_t			cstlen;
2f0331
	uint32_t			objlen;
2f0331
	uint32_t			aattr;
2f0331
	uint32_t			sattr;
2f0331
	uint32_t			rattr;
2f0331
	uint16_t			oattr;
2f0331
	uint16_t			machine;
2f0331
	uint16_t			reltype;
2f0331
	uint32_t			relrva;
2f0331
	uint32_t			reclen;
2f0331
	uint32_t			recoff;
2f0331
	uint32_t			reloff;
2f0331
	uint32_t			symoff;
2f0331
	uint32_t			cstoff;
2f0331
	uint32_t			datoff;
2f0331
	uint32_t			stroff;
2f0331
2f0331
	if ((buflen = strlen(dctx->cctx->libname)) > 1024*1024)
2f0331
		return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA);
2f0331
2f0331
	liblen = (uint32_t)buflen;
2f0331
	cstlen = (3 * liblen) + 48;
2f0331
	objlen = sizeof(*dsometa) + cstlen;
2f0331
a3e2cf
	if (vobj->addr && (vobj->size < objlen))
2f0331
		return MDSO_BUFFER_ERROR(dctx);
2f0331
a3e2cf
	if ((addr = vobj->addr)) {
a3e2cf
		(void)0;
a3e2cf
a3e2cf
	} else {
a3e2cf
		vobj->size       = objlen;
9c013b
		vobj->mapstrsnum = 1;
9c013b
		vobj->mapstrslen = 10 + liblen;
2f0331
a3e2cf
		if (!vobj->name)
a3e2cf
			return 0;
a3e2cf
a3e2cf
		else if (mdso_create_object(dctx,vobj) < 0)
a3e2cf
			return MDSO_NESTED_ERROR(dctx);
a3e2cf
	}
2f0331
a3e2cf
	dsometa = (struct mdso_dsometa_object *)vobj->addr;
2f0331
2f0331
	if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) {
2f0331
		reclen  = sizeof(struct mdso_meta_record_m64);
2f0331
		aattr   = PE_IMAGE_SCN_ALIGN_16BYTES;
2f0331
		machine = PE_IMAGE_FILE_MACHINE_AMD64;
2f0331
		reltype = PE_IMAGE_REL_AMD64_ADDR64;
2f0331
		relrva  = 8;
2f0331
	} else {
2f0331
		reclen  = sizeof(struct mdso_meta_record_m32);
2f0331
		aattr   = PE_IMAGE_SCN_ALIGN_8BYTES;
2f0331
		machine = PE_IMAGE_FILE_MACHINE_I386;
2f0331
		reltype = PE_IMAGE_REL_I386_DIR32;
2f0331
		relrva  = 4;
2f0331
	}
2f0331
2f0331
	sattr  = PE_IMAGE_SCN_ALIGN_1BYTES;
2f0331
	sattr |= PE_IMAGE_SCN_MEM_READ;
2f0331
	sattr |= PE_IMAGE_SCN_CNT_INITIALIZED_DATA;
2f0331
2f0331
	rattr  = aattr;
2f0331
	rattr |= PE_IMAGE_SCN_MEM_READ;
2f0331
	rattr |= PE_IMAGE_SCN_CNT_INITIALIZED_DATA;
2f0331
2f0331
	oattr  = PE_IMAGE_FILE_LINE_NUMS_STRIPPED;
2f0331
	recoff = offsetof(struct mdso_dsometa_object,rec);
2f0331
	reloff = offsetof(struct mdso_dsometa_object,rel);
2f0331
	symoff = offsetof(struct mdso_dsometa_object,sym);
2f0331
	cstoff = offsetof(struct pe_raw_coff_strtbl,cst_data);
2f0331
	datoff = 0;
2f0331
2f0331
	stroff  = objlen - liblen - 16;
2f0331
	stroff += 0xf;
2f0331
	stroff |= 0xf;
2f0331
	stroff ^= 0xf;
2f0331
2f0331
	/* coff object header */
2f0331
	mdso_obj_write_short(dsometa->hdr.cfh_machine,machine);
2f0331
	mdso_obj_write_short(dsometa->hdr.cfh_num_of_sections,2);
2f0331
	mdso_obj_write_long(dsometa->hdr.cfh_ptr_to_sym_tbl,symoff);
2f0331
	mdso_obj_write_long(dsometa->hdr.cfh_num_of_syms,8);
2f0331
	mdso_obj_write_short(dsometa->hdr.cfh_characteristics,oattr);
2f0331
2f0331
	/* .dsostrs section header */
2f0331
	memcpy(dsometa->sec[0].sh_name,".dsostrs",8);
2f0331
	mdso_obj_write_long(dsometa->sec[0].sh_size_of_raw_data,liblen+1);
2f0331
	mdso_obj_write_long(dsometa->sec[0].sh_ptr_to_raw_data,stroff);
2f0331
	mdso_obj_write_long(dsometa->sec[0].sh_characteristics,sattr);
2f0331
2f0331
	/* .dsometa section header */
2f0331
	memcpy(dsometa->sec[1].sh_name,".dsometa",8);
2f0331
	mdso_obj_write_long(dsometa->sec[1].sh_size_of_raw_data,reclen);
2f0331
	mdso_obj_write_long(dsometa->sec[1].sh_ptr_to_raw_data,recoff);
2f0331
	mdso_obj_write_long(dsometa->sec[1].sh_ptr_to_relocs,reloff);
2f0331
	mdso_obj_write_short(dsometa->sec[1].sh_num_of_relocs,1);
2f0331
	mdso_obj_write_long(dsometa->sec[1].sh_characteristics,rattr);
2f0331
2f0331
	/* .dsometa section data: flags */
2f0331
	mark = dsometa->rec[0].data;
2f0331
	mdso_obj_write_long(&mark[2*relrva],dctx->cctx->dsoflags);
2f0331
2f0331
	/* .dsometa relocation record: .name */
2f0331
	mdso_obj_write_long(dsometa->rel[0].rel_sym,6);
2f0331
	mdso_obj_write_long(dsometa->rel[0].rel_rva,relrva);
2f0331
	mdso_obj_write_short(dsometa->rel[0].rel_type,reltype);
2f0331
2f0331
	/* coff string table */
2f0331
	mdso_obj_write_long(dsometa->cst.cst_size,cstlen);
2f0331
2f0331
	/* coff symbol table */
2f0331
	symrec = dsometa->sym;
2f0331
	mark   = dsometa->cst.cst_data;
2f0331
2f0331
	/* coff symbol: .file */
2f0331
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_FILE;
2f0331
	symrec[0].cs_num_of_aux_symbols[0] = 1;
2f0331
2f0331
	mdso_obj_write_short(&symrec[0].cs_section_number[0],PE_IMAGE_SYM_DEBUG);
2f0331
	mdso_obj_write_long(&symrec[1].cs_name[4],cstoff+datoff);
2f0331
2f0331
	memcpy(symrec[0].cs_name,".file",5);
2f0331
	memcpy(&mark[0],".dsometa_",9);
2f0331
	memcpy(&mark[9],dctx->cctx->libname,liblen);
2f0331
	memcpy(&mark[9+liblen],".s",2);
2f0331
2f0331
	datoff += 12 + liblen;
2f0331
	mark   += 12 + liblen;
2f0331
	symrec += 2;
2f0331
2f0331
	/* coff symbol: .dsostrs */
2f0331
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
2f0331
	symrec[0].cs_num_of_aux_symbols[0] = 1;
2f0331
2f0331
	mdso_obj_write_short(symrec[0].cs_section_number,1);
2f0331
	memcpy(symrec[0].cs_name,".dsostrs",8);
2f0331
bbf7fc
	aux = (struct pe_raw_aux_rec_section *)&symrec[1];
2f0331
	mdso_obj_write_long(aux->aux_size,liblen+1);
2f0331
	mdso_obj_write_short(aux->aux_num_of_relocs,0);
2f0331
2f0331
	datoff += 0;
2f0331
	mark   += 0;
2f0331
	symrec += 2;
2f0331
2f0331
	/* coff symbol: .dsometa */
2f0331
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
2f0331
	symrec[0].cs_num_of_aux_symbols[0] = 1;
2f0331
2f0331
	mdso_obj_write_short(symrec[0].cs_section_number,2);
2f0331
	memcpy(symrec[0].cs_name,".dsometa",8);
2f0331
bbf7fc
	aux = (struct pe_raw_aux_rec_section *)&symrec[1];
2f0331
	mdso_obj_write_long(aux->aux_size,reclen);
2f0331
	mdso_obj_write_short(aux->aux_num_of_relocs,1);
2f0331
2f0331
	datoff += 0;
2f0331
	mark   += 0;
2f0331
	symrec += 2;
2f0331
2f0331
	/* coff symbol: .libname */
2f0331
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
2f0331
	symrec[0].cs_num_of_aux_symbols[0] = 0;
2f0331
2f0331
	mdso_obj_write_short(symrec[0].cs_section_number,1);
2f0331
	memcpy(symrec[0].cs_name,".libname",8);
2f0331
2f0331
	datoff += 0;
2f0331
	mark   += 0;
2f0331
	symrec += 1;
2f0331
2f0331
	/* coff symbol: .dsometa_libname */
2f0331
	symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL;
2f0331
	symrec[0].cs_num_of_aux_symbols[0] = 0;
2f0331
2f0331
	mdso_obj_write_short(symrec[0].cs_section_number,2);
2f0331
	mdso_obj_write_long(&symrec[0].cs_name[4],cstoff+datoff);
2f0331
2f0331
	memcpy(&mark[0],".dsometa_",9);
2f0331
	memcpy(&mark[9],dctx->cctx->libname,liblen);
2f0331
9c013b
	/* archive symbol map */
a3e2cf
	if (vobj->mapstrs)
9c013b
		memcpy(vobj->mapstrs,mark,9+liblen);
9c013b
2f0331
	/* .libname */
2f0331
	mark = dsometa->hdr.cfh_machine;
2f0331
	memcpy(&mark[stroff],dctx->cctx->libname,liblen);
2f0331
a3e2cf
	/* fs object unmap */
a3e2cf
	if (!addr)
a3e2cf
		munmap(vobj->addr,vobj->size);
2f0331
a3e2cf
	/* tada */
2f0331
	return 0;
2f0331
}