diff options
-rw-r--r-- | config.project | 1 | ||||
-rw-r--r-- | include/mdso/mdso.h | 12 | ||||
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | project/tree.mk | 1 | ||||
-rw-r--r-- | src/object/mdso_objgen_symfn.c | 226 |
5 files changed, 241 insertions, 0 deletions
diff --git a/config.project b/config.project index 36a65c7..0be248c 100644 --- a/config.project +++ b/config.project @@ -20,6 +20,7 @@ mb_default_shell=sh # switches mb_default_cflags_common="-std=c99 -D_XOPEN_SOURCE=700" mb_default_cflags_common="$mb_default_cflags_common -I\$(PROJECT_DIR)/src/internal" +mb_default_cflags_common="$mb_default_cflags_common -I\$(PROJECT_DIR)/src/internal/perk" mb_default_cflags_common="$mb_default_cflags_common -I\$(PROJECT_DIR)/include" mb_default_cflags_common="$mb_default_cflags_common -Ibuild" diff --git a/include/mdso/mdso.h b/include/mdso/mdso.h index c60979a..68676d2 100644 --- a/include/mdso/mdso.h +++ b/include/mdso/mdso.h @@ -49,6 +49,7 @@ enum mdso_custom_error { MDSO_ERR_FLEE_ERROR, MDSO_ERR_NULL_CONTEXT, MDSO_ERR_NULL_SOURCE, + MDSO_ERR_INVALID_DATA, MDSO_ERR_INVALID_CONTEXT, MDSO_ERR_INVALID_SOURCE, MDSO_ERR_SOURCE_SIZE_ZERO, @@ -67,6 +68,16 @@ struct mdso_input { size_t size; }; +struct mdso_object { + void * addr; + size_t size; + void * mapstrs; + uint32_t mapstrsnum; + uint32_t mapstrslen; + uint32_t arhdrpos; + uint32_t arhdrlen; +}; + struct mdso_error_info { const struct mdso_driver_ctx * edctx; const struct mdso_unit_ctx * euctx; @@ -136,6 +147,7 @@ mdso_api uint64_t mdso_crc64_mbstr (const unsigned char * str, size_t * symlen); mdso_api int mdso_asmgen_dsometa (const struct mdso_driver_ctx *, FILE * fout); mdso_api int mdso_asmgen_symentry (const struct mdso_driver_ctx *, const char * sym, FILE * fout); mdso_api int mdso_asmgen_symfn (const struct mdso_driver_ctx *, const char * sym, FILE * fout); +mdso_api int mdso_objgen_symfn (const struct mdso_driver_ctx *, const char * sym, FILE * fout, struct mdso_object *); #ifdef __cplusplus } diff --git a/project/common.mk b/project/common.mk index 26c2c7a..acd2eed 100644 --- a/project/common.mk +++ b/project/common.mk @@ -10,6 +10,7 @@ API_SRCS = \ src/logic/mdso_asmgen_symentry.c \ src/logic/mdso_asmgen_symfn.c \ src/logic/mdso_map_input.c \ + src/object/mdso_objgen_symfn.c \ src/output/mdso_output_error.c \ src/output/mdso_output_export_symbols.c \ src/skin/mdso_skin_default.c \ diff --git a/project/tree.mk b/project/tree.mk index 94db455..063788c 100644 --- a/project/tree.mk +++ b/project/tree.mk @@ -5,6 +5,7 @@ tree.tag: mkdir -p src/helper mkdir -p src/internal mkdir -p src/logic + mkdir -p src/object mkdir -p src/output mkdir -p src/skin touch tree.tag diff --git a/src/object/mdso_objgen_symfn.c b/src/object/mdso_objgen_symfn.c new file mode 100644 index 0000000..5644f4c --- /dev/null +++ b/src/object/mdso_objgen_symfn.c @@ -0,0 +1,226 @@ +/****************************************************************/ +/* mdso: midipix dso scavenger */ +/* Copyright (C) 2015--2017 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ +/****************************************************************/ + +#include <stdio.h> +#include <stddef.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <mdso/mdso.h> +#include "mdso_object_impl.h" +#include "mdso_errinfo_impl.h" +#include "perk_consts.h" +#include "perk_structs.h" + +static const unsigned char jmp_code_i386[16] = { + 0xff,0x25, + 0x0,0x0,0x0,0x0, + 0x90,0x90, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +}; + +static const unsigned char jmp_code_amd64[16] = { + 0xff,0x24,0x25, + 0x0,0x0,0x0,0x0, + 0x90, + 0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90 +}; + +struct mdso_symfn_code { + unsigned char code[16]; +}; + +struct mdso_symfn_object { + struct pe_raw_coff_object_hdr hdr; + struct pe_raw_sec_hdr sec[1]; + struct mdso_symfn_code cod[1]; + struct pe_raw_coff_reloc rel[1]; + struct pe_raw_coff_symbol sym[7]; + struct pe_raw_coff_strtbl cst; +}; + +int mdso_objgen_symfn( + const struct mdso_driver_ctx * dctx, + const char * sym, + FILE * fout, + struct mdso_object * vobj) +{ + struct mdso_symfn_object * symfn; + struct pe_raw_coff_symbol * symrec; + const unsigned char * code; + unsigned char * mark; + struct pe_aux_rec_section * aux; + size_t buflen; + uint32_t symlen; + uint32_t cstlen; + uint32_t objlen; + uint32_t aattr; + uint32_t sattr; + uint16_t oattr; + uint16_t machine; + uint16_t reltype; + uint32_t relrva; + uint32_t reloff; + uint32_t symoff; + uint32_t cstoff; + uint32_t codoff; + uint32_t datoff; + + if ((buflen = strlen(sym)) > 1024*1024) + return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA); + + symlen = (uint32_t)buflen; + cstlen = (3 * symlen) + 32; + objlen = sizeof(*symfn) + cstlen; + + if (vobj && vobj->addr && (vobj->size < objlen)) + return MDSO_BUFFER_ERROR(dctx); + + if (vobj && !vobj->addr) { + vobj->size = objlen; + return 0; + } + + if (vobj) + symfn = (struct mdso_symfn_object *)vobj->addr; + + else if (!(symfn = calloc(1,objlen))) + return MDSO_SYSTEM_ERROR(dctx); + + if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) { + code = jmp_code_amd64; + aattr = PE_IMAGE_SCN_ALIGN_16BYTES; + machine = PE_IMAGE_FILE_MACHINE_AMD64; + reltype = PE_IMAGE_REL_AMD64_ADDR32; + relrva = 3; + } else { + code = jmp_code_i386; + aattr = PE_IMAGE_SCN_ALIGN_4BYTES; + machine = PE_IMAGE_FILE_MACHINE_I386; + reltype = PE_IMAGE_REL_I386_DIR32; + relrva = 2; + } + + sattr = aattr; + sattr |= PE_IMAGE_SCN_MEM_READ; + sattr |= PE_IMAGE_SCN_MEM_EXECUTE; + sattr |= PE_IMAGE_SCN_CNT_CODE; + + oattr = PE_IMAGE_FILE_LINE_NUMS_STRIPPED; + reloff = offsetof(struct mdso_symfn_object,rel); + symoff = offsetof(struct mdso_symfn_object,sym); + codoff = offsetof(struct mdso_symfn_object,cod); + cstoff = offsetof(struct pe_raw_coff_strtbl,cst_data); + datoff = 0; + + /* coff object header */ + mdso_obj_write_short(symfn->hdr.cfh_machine,machine); + mdso_obj_write_short(symfn->hdr.cfh_num_of_sections,1); + mdso_obj_write_long(symfn->hdr.cfh_ptr_to_sym_tbl,symoff); + mdso_obj_write_long(symfn->hdr.cfh_num_of_syms,7); + mdso_obj_write_short(symfn->hdr.cfh_characteristics,oattr); + + /* .text section header */ + memcpy(symfn->sec[0].sh_name,".text",5); + mdso_obj_write_long(symfn->sec[0].sh_size_of_raw_data,16); + mdso_obj_write_long(symfn->sec[0].sh_ptr_to_raw_data,codoff); + mdso_obj_write_long(symfn->sec[0].sh_ptr_to_relocs,reloff); + mdso_obj_write_short(symfn->sec[0].sh_num_of_relocs,1); + mdso_obj_write_long(symfn->sec[0].sh_characteristics,sattr); + + /* .text section content */ + memcpy(symfn->cod,code,16); + + /* .text relocation record */ + mdso_obj_write_long(symfn->rel[0].rel_sym,6); + mdso_obj_write_long(symfn->rel[0].rel_rva,relrva); + mdso_obj_write_short(symfn->rel[0].rel_type,reltype); + + /* coff string table */ + mdso_obj_write_long(symfn->cst.cst_size,cstlen); + + /* coff symbol table */ + symrec = symfn->sym; + mark = symfn->cst.cst_data; + + /* coff symbol: .file */ + symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_FILE; + symrec[0].cs_num_of_aux_symbols[0] = 1; + + mdso_obj_write_short(&symrec[0].cs_section_number[0],PE_IMAGE_SYM_DEBUG); + mdso_obj_write_long(&symrec[1].cs_name[4],cstoff+datoff); + + memcpy(symrec[0].cs_name,".file",5); + memcpy(&mark[0],"__",2); + memcpy(&mark[2],sym,symlen); + memcpy(&mark[2+symlen],"_sym_fn.s",9); + + datoff += 12 + symlen; + mark += 12 + symlen; + symrec += 2; + + /* coff symbol: .text */ + symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC; + symrec[0].cs_num_of_aux_symbols[0] = 1; + + mdso_obj_write_short(symrec[0].cs_section_number,1); + memcpy(symrec[0].cs_name,".text",5); + + aux = (struct pe_aux_rec_section *)&symrec[1]; + mdso_obj_write_long(aux->aux_size,relrva+4); + mdso_obj_write_short(aux->aux_num_of_relocs,1); + + datoff += 0; + mark += 0; + symrec += 2; + + /* coff symbol: sym */ + symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL; + symrec[0].cs_num_of_aux_symbols[0] = 1; + + mdso_obj_write_short(symrec[0].cs_type,PE_IMAGE_SYM_DTYPE_FUNCTION<<8); + mdso_obj_write_short(symrec[0].cs_section_number,1); + mdso_obj_write_long(&symrec[0].cs_name[4],cstoff+datoff); + + if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) { + memcpy(&mark[0],sym,symlen); + } else { + memcpy(&mark[1],sym,symlen); + mark[0] = '_'; + datoff++; + mark++; + } + + datoff += 1 + symlen; + mark += 1 + symlen; + symrec += 2; + + /* coff symbol: __imp_sym */ + symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL; + symrec[0].cs_num_of_aux_symbols[0] = 0; + + mdso_obj_write_short(symrec[0].cs_section_number,0); + mdso_obj_write_long(&symrec[0].cs_name[4],cstoff+datoff); + + if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) { + memcpy(&mark[0],"__imp_",6); + memcpy(&mark[6],sym,symlen); + } else { + memcpy(&mark[0],"__imp_",6); + memcpy(&mark[7],sym,symlen); + mark[6] = '_'; + datoff++; + mark++; + } + + /* tada */ + if (fout) + if (fwrite(symfn,objlen,1,fout) == 0) + return MDSO_FILE_ERROR(dctx); + + return 0; +} |