|
|
bc1dc4 |
/****************************************************************/
|
|
|
bc1dc4 |
/* mdso: midipix dso scavenger */
|
|
|
473806 |
/* Copyright (C) 2015--2024 SysDeer Technologies, LLC */
|
|
|
bc1dc4 |
/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */
|
|
|
bc1dc4 |
/****************************************************************/
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
#include <stdio.h>
|
|
|
bc1dc4 |
#include <stddef.h>
|
|
|
bc1dc4 |
#include <stdint.h>
|
|
|
bc1dc4 |
#include <stdlib.h>
|
|
|
bc1dc4 |
#include <string.h>
|
|
|
a3e2cf |
#include <sys/mman.h>
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
#include <mdso/mdso.h>
|
|
|
c26232 |
#include <mdso/mdso_specs.h>
|
|
|
bc1dc4 |
#include "mdso_object_impl.h"
|
|
|
bc1dc4 |
#include "mdso_errinfo_impl.h"
|
|
|
bc1dc4 |
#include "perk_consts.h"
|
|
|
bc1dc4 |
#include "perk_structs.h"
|
|
|
bc1dc4 |
|
|
|
c26232 |
struct mdso_symfn_refs {
|
|
|
c26232 |
unsigned char refs[16];
|
|
|
bc1dc4 |
};
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
struct mdso_symentry_object {
|
|
|
bc1dc4 |
struct pe_raw_coff_object_hdr hdr;
|
|
|
bc1dc4 |
struct pe_raw_sec_hdr sec[2];
|
|
|
c26232 |
struct mdso_symfn_refs ref[1];
|
|
|
bc1dc4 |
struct pe_raw_coff_reloc rel[2];
|
|
|
bc1dc4 |
struct pe_raw_coff_symbol sym[9];
|
|
|
bc1dc4 |
struct pe_raw_coff_strtbl cst;
|
|
|
bc1dc4 |
};
|
|
|
bc1dc4 |
|
|
|
6a7467 |
static void mdso_obj_write_secoff(unsigned char * ch, uint64_t secoff)
|
|
|
6a7467 |
{
|
|
|
6a7467 |
*ch++ = '/';
|
|
|
6a7467 |
mdso_obj_write_dec(ch,secoff);
|
|
|
6a7467 |
}
|
|
|
6a7467 |
|
|
|
6a7467 |
static void mdso_obj_write_sym_symentry(char * ch, const char * sym)
|
|
|
6a7467 |
{
|
|
|
6a7467 |
*ch++ = '.';
|
|
|
6a7467 |
|
|
|
6a7467 |
for (; *sym; )
|
|
|
6a7467 |
*ch++ = *sym++;
|
|
|
6a7467 |
|
|
|
6a7467 |
memcpy(ch,"_symentry.s",11);
|
|
|
6a7467 |
}
|
|
|
6a7467 |
|
|
|
6a7467 |
static void mdso_obj_write_sym_symstr(char * ch, const char * sym)
|
|
|
6a7467 |
{
|
|
|
6a7467 |
memcpy(ch,".symstr_",8);
|
|
|
6a7467 |
ch = &ch[8];
|
|
|
6a7467 |
|
|
|
6a7467 |
for (; *sym; )
|
|
|
6a7467 |
*ch++ = *sym++;
|
|
|
6a7467 |
}
|
|
|
6a7467 |
|
|
|
6a7467 |
static void mdso_obj_write_sym_impstr(char * ch, uint32_t uscore, const char * sym)
|
|
|
6a7467 |
{
|
|
|
6a7467 |
memcpy(ch,"__imp_",6);
|
|
|
6a7467 |
ch = &ch[6];
|
|
|
6a7467 |
|
|
|
6a7467 |
if (uscore)
|
|
|
6a7467 |
*ch++ = '_';
|
|
|
6a7467 |
|
|
|
6a7467 |
for (; *sym; )
|
|
|
6a7467 |
*ch++ = *sym++;
|
|
|
6a7467 |
}
|
|
|
6a7467 |
|
|
|
6a7467 |
static void mdso_obj_write_sym_secstr(char * ch, const char * secname, const char * sym)
|
|
|
6a7467 |
{
|
|
|
6a7467 |
for (; *secname; )
|
|
|
6a7467 |
*ch++ = *secname++;
|
|
|
6a7467 |
|
|
|
6a7467 |
*ch++ = '$';
|
|
|
6a7467 |
|
|
|
6a7467 |
for (; *sym; )
|
|
|
6a7467 |
*ch++ = *sym++;
|
|
|
6a7467 |
}
|
|
|
6a7467 |
|
|
|
6a7467 |
static void mdso_obj_write_libname(char * ch, const char * secname, const char * sym)
|
|
|
6a7467 |
{
|
|
|
6a7467 |
for (; *secname; )
|
|
|
6a7467 |
*ch++ = *secname++;
|
|
|
6a7467 |
|
|
|
6a7467 |
*ch++ = '_';
|
|
|
6a7467 |
|
|
|
6a7467 |
for (; *sym; )
|
|
|
6a7467 |
*ch++ = *sym++;
|
|
|
6a7467 |
}
|
|
|
6a7467 |
|
|
|
bc1dc4 |
int mdso_objgen_symentry(
|
|
|
bc1dc4 |
const struct mdso_driver_ctx * dctx,
|
|
|
bc1dc4 |
const char * sym,
|
|
|
bc1dc4 |
struct mdso_object * vobj)
|
|
|
bc1dc4 |
{
|
|
|
bc1dc4 |
struct mdso_symentry_object * syment;
|
|
|
bc1dc4 |
struct pe_raw_coff_symbol * symrec;
|
|
|
a3e2cf |
void * addr;
|
|
|
c26232 |
void * mark;
|
|
|
c26232 |
char * ch;
|
|
|
c26232 |
char * strtbl;
|
|
|
bbf7fc |
struct pe_raw_aux_rec_section * aux;
|
|
|
bc1dc4 |
size_t liblen;
|
|
|
bc1dc4 |
uint32_t symlen;
|
|
|
c26232 |
size_t cstlen;
|
|
|
bc1dc4 |
uint32_t objlen;
|
|
|
bc1dc4 |
uint32_t aattr;
|
|
|
bc1dc4 |
uint32_t sattr;
|
|
|
bc1dc4 |
uint32_t rattr;
|
|
|
bc1dc4 |
uint16_t oattr;
|
|
|
bc1dc4 |
uint16_t machine;
|
|
|
bc1dc4 |
uint16_t reltype;
|
|
|
bc1dc4 |
uint32_t relrva;
|
|
|
bc1dc4 |
uint32_t refoff;
|
|
|
bc1dc4 |
uint32_t reloff;
|
|
|
bc1dc4 |
uint32_t symoff;
|
|
|
9c013b |
uint32_t uscore;
|
|
|
c26232 |
uint32_t stroff;
|
|
|
c26232 |
uint32_t stroff_cstdata;
|
|
|
c26232 |
uint32_t stroff_file;
|
|
|
c26232 |
uint32_t stroff_dsosyms;
|
|
|
c26232 |
uint32_t stroff_dsostrs;
|
|
|
c26232 |
uint32_t stroff_symstr;
|
|
|
c26232 |
uint32_t stroff_impsym;
|
|
|
c26232 |
uint32_t stroff_libname;
|
|
|
c26232 |
uint32_t stroff_null;
|
|
|
c26232 |
|
|
|
c26232 |
if ((symlen = (uint32_t)strlen(sym)) > 1024*1024)
|
|
|
bc1dc4 |
return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
if ((liblen = strlen(dctx->cctx->libname)) > 1024*1024)
|
|
|
bc1dc4 |
return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_DATA);
|
|
|
bc1dc4 |
|
|
|
c26232 |
stroff_cstdata = offsetof(struct pe_raw_coff_strtbl,cst_data);
|
|
|
c26232 |
stroff_file = stroff_cstdata;
|
|
|
c26232 |
stroff_dsosyms = stroff_file + 13 + symlen; /* .foo_symentry.s */
|
|
|
c26232 |
stroff_dsostrs = stroff_dsosyms + 10 + symlen; /* .dsosyms$foo */
|
|
|
c26232 |
stroff_symstr = stroff_dsostrs + 10 + symlen; /* .dsostrs$foo */
|
|
|
c26232 |
stroff_impsym = stroff_symstr + 9 + symlen; /* .symstr_foo */
|
|
|
c26232 |
stroff_libname = stroff_impsym + 8 + symlen; /* __imp__foo */
|
|
|
c26232 |
stroff_null = stroff_libname + 10 + liblen; /* .dsometa_libname */
|
|
|
c26232 |
|
|
|
c26232 |
stroff = offsetof(struct mdso_symentry_object,cst) + stroff_null;
|
|
|
c26232 |
stroff += 0xf;
|
|
|
c26232 |
stroff |= 0xf;
|
|
|
c26232 |
stroff ^= 0xf;
|
|
|
c26232 |
|
|
|
c26232 |
cstlen = stroff_null;
|
|
|
c26232 |
objlen = stroff + symlen + 1;
|
|
|
c26232 |
uscore = !(dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR);
|
|
|
bc1dc4 |
|
|
|
a3e2cf |
if (vobj->addr && (vobj->size < objlen))
|
|
|
bc1dc4 |
return MDSO_BUFFER_ERROR(dctx);
|
|
|
bc1dc4 |
|
|
|
a3e2cf |
if ((addr = vobj->addr)) {
|
|
|
a3e2cf |
(void)0;
|
|
|
a3e2cf |
|
|
|
a3e2cf |
} else {
|
|
|
a3e2cf |
vobj->size = objlen;
|
|
|
9c013b |
vobj->mapstrsnum = 1;
|
|
|
9c013b |
vobj->mapstrslen = 7 + uscore + symlen;
|
|
|
bc1dc4 |
|
|
|
a3e2cf |
if (!vobj->name)
|
|
|
a3e2cf |
return 0;
|
|
|
a3e2cf |
|
|
|
a3e2cf |
else if (mdso_create_object(dctx,vobj) < 0)
|
|
|
a3e2cf |
return MDSO_NESTED_ERROR(dctx);
|
|
|
a3e2cf |
}
|
|
|
bc1dc4 |
|
|
|
a3e2cf |
syment = (struct mdso_symentry_object *)vobj->addr;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
if (dctx->cctx->drvflags & MDSO_DRIVER_QUAD_PTR) {
|
|
|
bc1dc4 |
aattr = PE_IMAGE_SCN_ALIGN_16BYTES;
|
|
|
bc1dc4 |
machine = PE_IMAGE_FILE_MACHINE_AMD64;
|
|
|
54e94f |
reltype = PE_IMAGE_REL_AMD64_ADDR32NB;
|
|
|
bc1dc4 |
relrva = 8;
|
|
|
bc1dc4 |
} else {
|
|
|
bc1dc4 |
aattr = PE_IMAGE_SCN_ALIGN_4BYTES;
|
|
|
bc1dc4 |
machine = PE_IMAGE_FILE_MACHINE_I386;
|
|
|
54e94f |
reltype = PE_IMAGE_REL_I386_DIR32NB;
|
|
|
bc1dc4 |
relrva = 4;
|
|
|
bc1dc4 |
}
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
sattr = PE_IMAGE_SCN_ALIGN_1BYTES;
|
|
|
bc1dc4 |
sattr |= PE_IMAGE_SCN_MEM_READ;
|
|
|
bc1dc4 |
sattr |= PE_IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
|
c26232 |
sattr |= PE_IMAGE_SCN_LNK_COMDAT;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
rattr = aattr;
|
|
|
bc1dc4 |
rattr |= PE_IMAGE_SCN_MEM_READ;
|
|
|
bc1dc4 |
rattr |= PE_IMAGE_SCN_CNT_INITIALIZED_DATA;
|
|
|
c26232 |
rattr |= PE_IMAGE_SCN_LNK_COMDAT;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
oattr = PE_IMAGE_FILE_LINE_NUMS_STRIPPED;
|
|
|
bc1dc4 |
refoff = offsetof(struct mdso_symentry_object,ref);
|
|
|
bc1dc4 |
reloff = offsetof(struct mdso_symentry_object,rel);
|
|
|
bc1dc4 |
symoff = offsetof(struct mdso_symentry_object,sym);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff object header */
|
|
|
bc1dc4 |
mdso_obj_write_short(syment->hdr.cfh_machine,machine);
|
|
|
bc1dc4 |
mdso_obj_write_short(syment->hdr.cfh_num_of_sections,2);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->hdr.cfh_ptr_to_sym_tbl,symoff);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->hdr.cfh_num_of_syms,9);
|
|
|
bc1dc4 |
mdso_obj_write_short(syment->hdr.cfh_characteristics,oattr);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* .dsostrs section header */
|
|
|
6a7467 |
mdso_obj_write_secoff(syment->sec[0].sh_name,stroff_dsostrs);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[0].sh_size_of_raw_data,symlen+1);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[0].sh_ptr_to_raw_data,stroff);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[0].sh_characteristics,sattr);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* .dsosyms section header */
|
|
|
6a7467 |
mdso_obj_write_secoff(syment->sec[1].sh_name,stroff_dsosyms);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[1].sh_size_of_raw_data,2*relrva);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[1].sh_ptr_to_raw_data,refoff);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[1].sh_ptr_to_relocs,reloff);
|
|
|
bc1dc4 |
mdso_obj_write_short(syment->sec[1].sh_num_of_relocs,2);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->sec[1].sh_characteristics,rattr);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* .dsosyms relocation record: .symstr */
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->rel[0].rel_sym,6);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->rel[0].rel_rva,0);
|
|
|
bc1dc4 |
mdso_obj_write_short(syment->rel[0].rel_type,reltype);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* .dsosyms relocation record: .dsometa_libname */
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->rel[1].rel_sym,8);
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->rel[1].rel_rva,relrva);
|
|
|
bc1dc4 |
mdso_obj_write_short(syment->rel[1].rel_type,reltype);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff string table */
|
|
|
bc1dc4 |
mdso_obj_write_long(syment->cst.cst_size,cstlen);
|
|
|
c26232 |
mark = &syment->cst;
|
|
|
c26232 |
strtbl = mark;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff symbol table */
|
|
|
bc1dc4 |
symrec = syment->sym;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff symbol: .file */
|
|
|
bc1dc4 |
symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_FILE;
|
|
|
bc1dc4 |
symrec[0].cs_num_of_aux_symbols[0] = 1;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
mdso_obj_write_short(&symrec[0].cs_section_number[0],PE_IMAGE_SYM_DEBUG);
|
|
|
c26232 |
mdso_obj_write_long(&symrec[1].cs_name[4],stroff_file);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
memcpy(symrec[0].cs_name,".file",5);
|
|
|
6a7467 |
mdso_obj_write_sym_symentry(&strtbl[stroff_file],sym);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
symrec += 2;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff symbol: .dsostrs */
|
|
|
bc1dc4 |
symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
|
|
|
bc1dc4 |
symrec[0].cs_num_of_aux_symbols[0] = 1;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
mdso_obj_write_short(symrec[0].cs_section_number,1);
|
|
|
c26232 |
mdso_obj_write_long(&symrec[0].cs_name[4],stroff_dsostrs);
|
|
|
6a7467 |
mdso_obj_write_sym_secstr(&strtbl[stroff_dsostrs],MDSO_STRS_SECTION,sym);
|
|
|
bc1dc4 |
|
|
|
bbf7fc |
aux = (struct pe_raw_aux_rec_section *)&symrec[1];
|
|
|
bc1dc4 |
mdso_obj_write_long(aux->aux_size,symlen+1);
|
|
|
bc1dc4 |
mdso_obj_write_short(aux->aux_num_of_relocs,0);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
symrec += 2;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff symbol: .dsosyms */
|
|
|
bc1dc4 |
symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
|
|
|
bc1dc4 |
symrec[0].cs_num_of_aux_symbols[0] = 1;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
mdso_obj_write_short(symrec[0].cs_section_number,2);
|
|
|
c26232 |
mdso_obj_write_long(&symrec[0].cs_name[4],stroff_dsosyms);
|
|
|
6a7467 |
mdso_obj_write_sym_secstr(&strtbl[stroff_dsosyms],MDSO_SYMS_SECTION,sym);
|
|
|
bc1dc4 |
|
|
|
bbf7fc |
aux = (struct pe_raw_aux_rec_section *)&symrec[1];
|
|
|
bc1dc4 |
mdso_obj_write_long(aux->aux_size,2*relrva);
|
|
|
bc1dc4 |
mdso_obj_write_short(aux->aux_num_of_relocs,2);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
symrec += 2;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff symbol: .symstr */
|
|
|
bc1dc4 |
symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_STATIC;
|
|
|
bc1dc4 |
symrec[0].cs_num_of_aux_symbols[0] = 0;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
mdso_obj_write_short(symrec[0].cs_section_number,1);
|
|
|
c26232 |
mdso_obj_write_long(&symrec[0].cs_name[4],stroff_symstr);
|
|
|
6a7467 |
mdso_obj_write_sym_symstr(&strtbl[stroff_symstr],sym);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
symrec += 1;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* coff symbol: __imp_sym */
|
|
|
bc1dc4 |
symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL;
|
|
|
bc1dc4 |
symrec[0].cs_num_of_aux_symbols[0] = 0;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
mdso_obj_write_short(symrec[0].cs_section_number,2);
|
|
|
c26232 |
mdso_obj_write_long(&symrec[0].cs_name[4],stroff_impsym);
|
|
|
6a7467 |
mdso_obj_write_sym_impstr(&strtbl[stroff_impsym],uscore,sym);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
symrec += 1;
|
|
|
bc1dc4 |
|
|
|
9c013b |
/* archive symbol map */
|
|
|
a3e2cf |
if (vobj->mapstrs)
|
|
|
c26232 |
strcpy(vobj->mapstrs,&strtbl[stroff_impsym]);
|
|
|
9c013b |
|
|
|
bc1dc4 |
/* coff symbol: .dsometa_libname */
|
|
|
bc1dc4 |
symrec[0].cs_storage_class[0] = PE_IMAGE_SYM_CLASS_EXTERNAL;
|
|
|
bc1dc4 |
symrec[0].cs_num_of_aux_symbols[0] = 0;
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
mdso_obj_write_short(symrec[0].cs_section_number,0);
|
|
|
c26232 |
mdso_obj_write_long(&symrec[0].cs_name[4],stroff_libname);
|
|
|
bc1dc4 |
|
|
|
6a7467 |
mdso_obj_write_libname(&strtbl[stroff_libname],
|
|
|
c26232 |
MDSO_META_SECTION,
|
|
|
c26232 |
dctx->cctx->libname);
|
|
|
bc1dc4 |
|
|
|
bc1dc4 |
/* .symstr */
|
|
|
c26232 |
mark = syment;
|
|
|
c26232 |
ch = mark;
|
|
|
c26232 |
memcpy(&ch[stroff],sym,symlen);
|
|
|
bc1dc4 |
|
|
|
a3e2cf |
/* fs object unmap */
|
|
|
a3e2cf |
if (!addr)
|
|
|
a3e2cf |
munmap(vobj->addr,vobj->size);
|
|
|
bc1dc4 |
|
|
|
a3e2cf |
/* tada */
|
|
|
bc1dc4 |
return 0;
|
|
|
bc1dc4 |
}
|