|
|
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;
|
|
|
9c013b |
unsigned char * mapsym;
|
|
|
bbf7fc |
struct pe_raw_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;
|
|
|
9c013b |
uint32_t uscore;
|
|
|
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;
|
|
|
9c013b |
uscore = !(dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR);
|
|
|
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;
|
|
|
9c013b |
vobj->mapstrsnum = 1;
|
|
|
9c013b |
vobj->mapstrslen = 1 + uscore + symlen;
|
|
|
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);
|
|
|
e5cc48 |
memcpy(&mark[0],".",1);
|
|
|
e5cc48 |
memcpy(&mark[1],sym,symlen);
|
|
|
e5cc48 |
memcpy(&mark[1+symlen],"_symfn.s",8);
|
|
|
97d39b |
|
|
|
e5cc48 |
datoff += 10 + symlen;
|
|
|
e5cc48 |
mark += 10 + 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 |
|
|
|
bbf7fc |
aux = (struct pe_raw_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 */
|
|
|
9c013b |
mapsym = mark;
|
|
|
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 |
|
|
|
9c013b |
/* archive symbol map */
|
|
|
9c013b |
if (vobj && vobj->mapstrs)
|
|
|
9c013b |
memcpy(vobj->mapstrs,mapsym,mark-mapsym);
|
|
|
9c013b |
|
|
|
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 |
|
|
|
a604e1 |
if (!vobj)
|
|
|
a604e1 |
free(symfn);
|
|
|
a604e1 |
|
|
|
97d39b |
return 0;
|
|
|
97d39b |
}
|