diff --git a/include/mdso/mdso.h b/include/mdso/mdso.h index 68676d2..7bbe894 100644 --- a/include/mdso/mdso.h +++ b/include/mdso/mdso.h @@ -147,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_symentry (const struct mdso_driver_ctx *, const char * sym, FILE * fout, struct mdso_object *); 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 acd2eed..89af04f 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_symentry.c \ src/object/mdso_objgen_symfn.c \ src/output/mdso_output_error.c \ src/output/mdso_output_export_symbols.c \ diff --git a/src/object/mdso_objgen_symentry.c b/src/object/mdso_objgen_symentry.c new file mode 100644 index 0000000..9dd22be --- /dev/null +++ b/src/object/mdso_objgen_symentry.c @@ -0,0 +1,257 @@ +/****************************************************************/ +/* mdso: midipix dso scavenger */ +/* Copyright (C) 2015--2017 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */ +/****************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include "mdso_object_impl.h" +#include "mdso_errinfo_impl.h" +#include "perk_consts.h" +#include "perk_structs.h" + +struct mdso_symfn_references { + unsigned char refs[16]; +}; + +struct mdso_symentry_object { + struct pe_raw_coff_object_hdr hdr; + struct pe_raw_sec_hdr sec[2]; + struct mdso_symfn_references ref[1]; + struct pe_raw_coff_reloc rel[2]; + struct pe_raw_coff_symbol sym[9]; + struct pe_raw_coff_strtbl cst; +}; + +int mdso_objgen_symentry( + const struct mdso_driver_ctx * dctx, + const char * sym, + FILE * fout, + struct mdso_object * vobj) +{ + struct mdso_symentry_object * syment; + struct pe_raw_coff_symbol * symrec; + unsigned char * mark; + struct pe_aux_rec_section * aux; + size_t buflen; + size_t liblen; + uint32_t symlen; + uint32_t cstlen; + uint32_t objlen; + uint32_t aattr; + uint32_t sattr; + uint32_t rattr; + uint16_t oattr; + uint16_t machine; + uint16_t reltype; + uint32_t relrva; + uint32_t refoff; + uint32_t reloff; + uint32_t symoff; + uint32_t cstoff; + uint32_t datoff; + uint32_t stroff; + + if ((buflen = strlen(sym)) > 1024*1024) + return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA); + + if ((liblen = strlen(dctx->cctx->libname)) > 1024*1024) + return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA); + + symlen = (uint32_t)buflen; + cstlen = (uint32_t)liblen + (3 * symlen) + 64; + objlen = sizeof(*syment) + cstlen; + + if (vobj && vobj->addr && (vobj->size < objlen)) + return MDSO_BUFFER_ERROR(dctx); + + if (vobj && !vobj->addr) { + vobj->size = objlen; + return 0; + } + + if (vobj) + syment = (struct mdso_symentry_object *)vobj->addr; + + else if (!(syment = calloc(1,objlen))) + return MDSO_SYSTEM_ERROR(dctx); + + if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) { + aattr = PE_IMAGE_SCN_ALIGN_16BYTES; + machine = PE_IMAGE_FILE_MACHINE_AMD64; + reltype = PE_IMAGE_REL_AMD64_ADDR64; + relrva = 8; + } else { + aattr = PE_IMAGE_SCN_ALIGN_4BYTES; + machine = PE_IMAGE_FILE_MACHINE_I386; + reltype = PE_IMAGE_REL_I386_DIR32; + relrva = 4; + } + + sattr = PE_IMAGE_SCN_ALIGN_1BYTES; + sattr |= PE_IMAGE_SCN_MEM_READ; + sattr |= PE_IMAGE_SCN_CNT_INITIALIZED_DATA; + + rattr = aattr; + rattr |= PE_IMAGE_SCN_MEM_READ; + rattr |= PE_IMAGE_SCN_CNT_INITIALIZED_DATA; + + oattr = PE_IMAGE_FILE_LINE_NUMS_STRIPPED; + refoff = offsetof(struct mdso_symentry_object,ref); + reloff = offsetof(struct mdso_symentry_object,rel); + symoff = offsetof(struct mdso_symentry_object,sym); + cstoff = offsetof(struct pe_raw_coff_strtbl,cst_data); + datoff = 0; + + stroff = objlen - symlen - 16; + stroff += 0xf; + stroff |= 0xf; + stroff ^= 0xf; + + /* coff object header */ + mdso_obj_write_short(syment->hdr.cfh_machine,machine); + mdso_obj_write_short(syment->hdr.cfh_num_of_sections,2); + mdso_obj_write_long(syment->hdr.cfh_ptr_to_sym_tbl,symoff); + mdso_obj_write_long(syment->hdr.cfh_num_of_syms,9); + mdso_obj_write_short(syment->hdr.cfh_characteristics,oattr); + + /* .dsostrs section header */ + memcpy(syment->sec[0].sh_name,".dsostrs",8); + mdso_obj_write_long(syment->sec[0].sh_size_of_raw_data,symlen+1); + mdso_obj_write_long(syment->sec[0].sh_ptr_to_raw_data,stroff); + mdso_obj_write_long(syment->sec[0].sh_characteristics,sattr); + + /* .dsosyms section header */ + memcpy(syment->sec[1].sh_name,".dsosyms",8); + mdso_obj_write_long(syment->sec[1].sh_size_of_raw_data,2*relrva); + mdso_obj_write_long(syment->sec[1].sh_ptr_to_raw_data,refoff); + mdso_obj_write_long(syment->sec[1].sh_ptr_to_relocs,reloff); + mdso_obj_write_short(syment->sec[1].sh_num_of_relocs,2); + mdso_obj_write_long(syment->sec[1].sh_characteristics,rattr); + + /* .dsosyms relocation record: .symstr */ + mdso_obj_write_long(syment->rel[0].rel_sym,6); + mdso_obj_write_long(syment->rel[0].rel_rva,0); + mdso_obj_write_short(syment->rel[0].rel_type,reltype); + + /* .dsosyms relocation record: .dsometa_libname */ + mdso_obj_write_long(syment->rel[1].rel_sym,8); + mdso_obj_write_long(syment->rel[1].rel_rva,relrva); + mdso_obj_write_short(syment->rel[1].rel_type,reltype); + + /* coff string table */ + mdso_obj_write_long(syment->cst.cst_size,cstlen); + + /* coff symbol table */ + symrec = syment->sym; + mark = syment->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_entry.s",12); + + datoff += 15 + symlen; + mark += 15 + symlen; + symrec += 2; + + /* coff symbol: .dsostrs */ + 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,".dsostrs",8); + + aux = (struct pe_aux_rec_section *)&symrec[1]; + mdso_obj_write_long(aux->aux_size,symlen+1); + mdso_obj_write_short(aux->aux_num_of_relocs,0); + + datoff += 0; + mark += 0; + symrec += 2; + + /* coff symbol: .dsosyms */ + 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,2); + memcpy(symrec[0].cs_name,".dsosyms",8); + + aux = (struct pe_aux_rec_section *)&symrec[1]; + mdso_obj_write_long(aux->aux_size,2*relrva); + mdso_obj_write_short(aux->aux_num_of_relocs,2); + + datoff += 0; + mark += 0; + symrec += 2; + + /* coff symbol: .symstr */ + symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC; + symrec[0].cs_num_of_aux_symbols[0] = 0; + + mdso_obj_write_short(symrec[0].cs_section_number,1); + memcpy(symrec[0].cs_name,".symstr",7); + + datoff += 0; + mark += 0; + symrec += 1; + + /* 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,2); + 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++; + } + + datoff += 7 + symlen; + mark += 7 + symlen; + symrec += 1; + + /* coff symbol: .dsometa_libname */ + 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); + + memcpy(&mark[0],".dsometa_",9); + memcpy(&mark[9],dctx->cctx->libname,liblen); + + /* .symstr */ + mark = syment->hdr.cfh_machine; + memcpy(&mark[stroff],sym,symlen); + + /* tada */ + if (fout) + if (fwrite(syment,objlen,1,fout) == 0) + return MDSO_FILE_ERROR(dctx); + + if (!vobj) + free(syment); + + return 0; +}