|
|
9c013b |
/****************************************************************/
|
|
|
9c013b |
/* mdso: midipix dso scavenger */
|
|
|
9c013b |
/* Copyright (C) 2015--2017 Z. Gilboa */
|
|
|
9c013b |
/* Released under GPLv2 and GPLv3; see COPYING.MDSO. */
|
|
|
9c013b |
/****************************************************************/
|
|
|
9c013b |
|
|
|
9c013b |
#include <stdint.h>
|
|
|
9c013b |
#include <stdio.h>
|
|
|
9c013b |
#include <stdlib.h>
|
|
|
9c013b |
#include <string.h>
|
|
|
9c013b |
|
|
|
9c013b |
#include <mdso/mdso.h>
|
|
|
9c013b |
#include "mdso_errinfo_impl.h"
|
|
|
9c013b |
#include "perk_structs.h"
|
|
|
9c013b |
|
|
|
9c013b |
static void mdso_argen_common_hdr(
|
|
|
9c013b |
struct pe_raw_archive_common_hdr * arhdr,
|
|
|
9c013b |
char * file_id,
|
|
|
9c013b |
size_t size)
|
|
|
9c013b |
{
|
|
|
9c013b |
size_t slen;
|
|
|
9c013b |
char sbuf[10];
|
|
|
9c013b |
|
|
|
9c013b |
memset(arhdr,0x20,sizeof(*arhdr));
|
|
|
9c013b |
|
|
|
9c013b |
slen = strlen(file_id);
|
|
|
9c013b |
memcpy(arhdr->ar_file_id,file_id,slen);
|
|
|
9c013b |
arhdr->ar_file_id[slen] = '/';
|
|
|
9c013b |
|
|
|
9c013b |
arhdr->ar_uid[0] = '0';
|
|
|
9c013b |
arhdr->ar_gid[0] = '0';
|
|
|
9c013b |
arhdr->ar_file_mode[0] = '0';
|
|
|
9c013b |
|
|
|
9c013b |
slen = sprintf(sbuf,"%zu",size);
|
|
|
9c013b |
memcpy(arhdr->ar_file_size,sbuf,slen);
|
|
|
9c013b |
|
|
|
9c013b |
arhdr->ar_end_tag[0] = 0x60;
|
|
|
9c013b |
arhdr->ar_end_tag[1] = 0x0a;
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
static void mdso_write_big_endian_long(unsigned char * ch, uint32_t val)
|
|
|
9c013b |
{
|
|
|
9c013b |
ch[3] = val;
|
|
|
9c013b |
ch[2] = val >> 8;
|
|
|
9c013b |
ch[1] = val >> 16;
|
|
|
9c013b |
ch[0] = val >> 24;
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
int mdso_argen_common(
|
|
|
9c013b |
const struct mdso_driver_ctx * dctx,
|
|
|
9c013b |
const char ** symv,
|
|
|
9c013b |
FILE * fout,
|
|
|
9c013b |
struct mdso_object * vobj)
|
|
|
9c013b |
{
|
|
|
9c013b |
int ret;
|
|
|
9c013b |
const char ** psym;
|
|
|
9c013b |
int nsym;
|
|
|
9c013b |
int nobj;
|
|
|
9c013b |
uint32_t objlen;
|
|
|
9c013b |
uint32_t hdrlen;
|
|
|
9c013b |
uint32_t mapstrsnum;
|
|
|
9c013b |
uint32_t mapstrslen;
|
|
|
9c013b |
uint32_t symidx;
|
|
|
9c013b |
unsigned char * ar;
|
|
|
9c013b |
unsigned char * mark;
|
|
|
9c013b |
unsigned char * idx;
|
|
|
9c013b |
char * mapstrs;
|
|
|
9c013b |
struct pe_raw_archive_common_hdr * arhdr;
|
|
|
9c013b |
struct mdso_object * pobj;
|
|
|
9c013b |
struct mdso_object * aobj;
|
|
|
9c013b |
struct mdso_object sobj[256];
|
|
|
9c013b |
char objname[16];
|
|
|
9c013b |
|
|
|
9c013b |
/* init */
|
|
|
9c013b |
memset (sobj,0,sizeof(sobj));
|
|
|
9c013b |
|
|
|
9c013b |
for (nsym=0,psym=symv; *psym; psym++)
|
|
|
9c013b |
nsym++;
|
|
|
9c013b |
|
|
|
9c013b |
if ((nobj = 2*nsym + 1) < 256)
|
|
|
9c013b |
aobj = sobj;
|
|
|
9c013b |
|
|
|
9c013b |
else if (nobj > 1024*1024)
|
|
|
9c013b |
return MDSO_CUSTOM_ERROR(dctx,MDSO_ERR_INVALID_VECTOR);
|
|
|
9c013b |
|
|
|
9c013b |
else if (!(aobj = calloc(1,nobj*sizeof(*aobj))))
|
|
|
9c013b |
return MDSO_SYSTEM_ERROR(dctx);
|
|
|
9c013b |
|
|
|
68360c |
/* objlen: archive signature, index header */
|
|
|
9c013b |
objlen = 8;
|
|
|
9c013b |
objlen += sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
|
|
|
68360c |
/* objlen: member headers */
|
|
|
9c013b |
ret = mdso_objgen_dsometa(dctx,0,aobj);
|
|
|
9c013b |
|
|
|
9c013b |
aobj->size += 1;
|
|
|
9c013b |
aobj->size |= 1;
|
|
|
9c013b |
aobj->size ^= 1;
|
|
|
9c013b |
|
|
|
9c013b |
objlen += aobj->size;
|
|
|
9c013b |
objlen += sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
|
|
|
9c013b |
mapstrslen = aobj->mapstrslen;
|
|
|
9c013b |
mapstrsnum = aobj->mapstrsnum;
|
|
|
9c013b |
|
|
|
9c013b |
for (psym=symv,pobj=&aobj[1]; *psym && !ret; psym++) {
|
|
|
9c013b |
ret = mdso_objgen_symfn(dctx,*psym,0,pobj);
|
|
|
9c013b |
|
|
|
9c013b |
pobj->size += 1;
|
|
|
9c013b |
pobj->size |= 1;
|
|
|
9c013b |
pobj->size ^= 1;
|
|
|
9c013b |
|
|
|
9c013b |
objlen += pobj->size;
|
|
|
9c013b |
objlen += sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
|
|
|
9c013b |
mapstrslen += pobj->mapstrslen;
|
|
|
9c013b |
mapstrsnum += pobj->mapstrsnum;
|
|
|
9c013b |
pobj++;
|
|
|
9c013b |
|
|
|
9c013b |
ret |= mdso_objgen_symentry(dctx,*psym,0,pobj);
|
|
|
9c013b |
|
|
|
9c013b |
pobj->size += 1;
|
|
|
9c013b |
pobj->size |= 1;
|
|
|
9c013b |
pobj->size ^= 1;
|
|
|
9c013b |
|
|
|
9c013b |
objlen += pobj->size;
|
|
|
9c013b |
objlen += sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
|
|
|
9c013b |
mapstrslen += pobj->mapstrslen;
|
|
|
9c013b |
mapstrsnum += pobj->mapstrsnum;
|
|
|
9c013b |
pobj++;
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
if (ret && (aobj != sobj))
|
|
|
9c013b |
free(aobj);
|
|
|
9c013b |
|
|
|
9c013b |
if (ret)
|
|
|
9c013b |
return ret;
|
|
|
9c013b |
|
|
|
68360c |
/* index: string block alignment */
|
|
|
9c013b |
mapstrslen += 1;
|
|
|
9c013b |
mapstrslen |= 1;
|
|
|
9c013b |
mapstrslen ^= 1;
|
|
|
9c013b |
|
|
|
68360c |
/* objlen: index size, padding */
|
|
|
68360c |
objlen += sizeof(uint32_t) * (1 + mapstrsnum);
|
|
|
68360c |
objlen += mapstrslen;
|
|
|
68360c |
|
|
|
9c013b |
objlen += 15;
|
|
|
9c013b |
objlen |= 15;
|
|
|
9c013b |
objlen ^= 15;
|
|
|
9c013b |
|
|
|
9c013b |
if (vobj && vobj->addr && (vobj->size < objlen))
|
|
|
9c013b |
return MDSO_BUFFER_ERROR(dctx);
|
|
|
9c013b |
|
|
|
9c013b |
if (vobj && !vobj->addr) {
|
|
|
9c013b |
vobj->size = objlen;
|
|
|
9c013b |
vobj->mapstrslen = mapstrslen;
|
|
|
9c013b |
vobj->mapstrsnum = mapstrsnum;
|
|
|
9c013b |
return 0;
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
if (vobj)
|
|
|
9c013b |
ar = (unsigned char *)vobj->addr;
|
|
|
9c013b |
|
|
|
9c013b |
else if (!(ar = calloc(1,objlen))) {
|
|
|
9c013b |
if (aobj != sobj)
|
|
|
9c013b |
free(aobj);
|
|
|
9c013b |
|
|
|
9c013b |
return MDSO_SYSTEM_ERROR(dctx);
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
/* archive signature */
|
|
|
9c013b |
memcpy(ar,"!<arch>\n",8);
|
|
|
9c013b |
mark = &ar[8];
|
|
|
9c013b |
|
|
|
9c013b |
/* archive header */
|
|
|
9c013b |
arhdr = (struct pe_raw_archive_common_hdr *)mark;
|
|
|
9c013b |
hdrlen = sizeof(uint32_t) * (1 + mapstrsnum) + mapstrslen;
|
|
|
9c013b |
mdso_argen_common_hdr(arhdr,"",hdrlen);
|
|
|
9c013b |
mark += sizeof(*arhdr);
|
|
|
9c013b |
|
|
|
9c013b |
/* archive index initialization */
|
|
|
9c013b |
mdso_write_big_endian_long(mark,mapstrsnum);
|
|
|
9c013b |
mark += sizeof(uint32_t);
|
|
|
9c013b |
|
|
|
9c013b |
idx = mark;
|
|
|
9c013b |
mark += sizeof(uint32_t) * mapstrsnum;
|
|
|
9c013b |
|
|
|
9c013b |
mapstrs = (char *)mark;
|
|
|
9c013b |
mark += mapstrslen;
|
|
|
9c013b |
|
|
|
9c013b |
/* .dsometa object */
|
|
|
9c013b |
aobj->mapstrs = mapstrs;
|
|
|
9c013b |
aobj->arhdrpos = (uint32_t)(mark - ar);
|
|
|
9c013b |
aobj->arhdrlen = sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
aobj->addr = &mark[aobj->arhdrlen];
|
|
|
9c013b |
|
|
|
9c013b |
for (symidx=0; symidx<aobj->mapstrsnum; symidx++) {
|
|
|
9c013b |
mdso_write_big_endian_long(idx,aobj->arhdrpos);
|
|
|
9c013b |
idx += sizeof(uint32_t);
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
ret = mdso_objgen_dsometa(dctx,0,aobj);
|
|
|
9c013b |
|
|
|
9c013b |
mdso_argen_common_hdr(
|
|
|
9c013b |
(struct pe_raw_archive_common_hdr *)mark,
|
|
|
9c013b |
".dsometa.o",aobj->size);
|
|
|
9c013b |
|
|
|
9c013b |
mark += aobj->arhdrlen + aobj->size;
|
|
|
9c013b |
mapstrs += aobj->mapstrslen;
|
|
|
9c013b |
|
|
|
9c013b |
/* archive symfn and symentry objects */
|
|
|
9c013b |
for (psym=symv,pobj=&aobj[1]; *psym && !ret; psym++) {
|
|
|
9c013b |
/* symfn object */
|
|
|
9c013b |
pobj->mapstrs = mapstrs;
|
|
|
9c013b |
pobj->arhdrpos = (uint32_t)(mark - ar);
|
|
|
9c013b |
pobj->arhdrlen = sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
pobj->addr = &mark[pobj->arhdrlen];
|
|
|
9c013b |
|
|
|
9c013b |
for (symidx=0; symidx<pobj->mapstrsnum; symidx++) {
|
|
|
9c013b |
mdso_write_big_endian_long(idx,pobj->arhdrpos);
|
|
|
9c013b |
idx += sizeof(uint32_t);
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
ret = mdso_objgen_symfn(dctx,*psym,0,pobj);
|
|
|
9c013b |
|
|
|
9c013b |
sprintf(
|
|
|
9c013b |
objname,"f%06zu.o",
|
|
|
9c013b |
psym - symv);
|
|
|
9c013b |
|
|
|
9c013b |
mdso_argen_common_hdr(
|
|
|
9c013b |
(struct pe_raw_archive_common_hdr *)mark,
|
|
|
9c013b |
objname,pobj->size);
|
|
|
9c013b |
|
|
|
9c013b |
mark += pobj->arhdrlen + pobj->size;
|
|
|
9c013b |
mapstrs += pobj->mapstrslen;
|
|
|
9c013b |
pobj++;
|
|
|
9c013b |
|
|
|
9c013b |
|
|
|
9c013b |
/* symentry object */
|
|
|
9c013b |
pobj->mapstrs = mapstrs;
|
|
|
9c013b |
pobj->arhdrpos = (uint32_t)(mark - ar);
|
|
|
9c013b |
pobj->arhdrlen = sizeof(struct pe_raw_archive_common_hdr);
|
|
|
9c013b |
pobj->addr = &mark[pobj->arhdrlen];
|
|
|
9c013b |
|
|
|
9c013b |
for (symidx=0; symidx<pobj->mapstrsnum; symidx++) {
|
|
|
9c013b |
mdso_write_big_endian_long(idx,pobj->arhdrpos);
|
|
|
9c013b |
idx += sizeof(uint32_t);
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
sprintf(
|
|
|
9c013b |
objname,"s%06zu.o",
|
|
|
9c013b |
psym - symv);
|
|
|
9c013b |
|
|
|
9c013b |
ret = mdso_objgen_symentry(dctx,*psym,0,pobj);
|
|
|
9c013b |
|
|
|
9c013b |
mdso_argen_common_hdr(
|
|
|
9c013b |
(struct pe_raw_archive_common_hdr *)mark,
|
|
|
9c013b |
objname,pobj->size);
|
|
|
9c013b |
|
|
|
9c013b |
mark += pobj->arhdrlen + pobj->size;
|
|
|
9c013b |
mapstrs += pobj->mapstrslen;
|
|
|
9c013b |
pobj++;
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
if (ret) {
|
|
|
9c013b |
if (aobj != sobj)
|
|
|
9c013b |
free(aobj);
|
|
|
9c013b |
|
|
|
9c013b |
if (!vobj)
|
|
|
9c013b |
free(ar);
|
|
|
9c013b |
|
|
|
9c013b |
return ret;
|
|
|
9c013b |
}
|
|
|
9c013b |
|
|
|
9c013b |
/* tada */
|
|
|
9c013b |
if (fout)
|
|
|
9c013b |
ret = fwrite(ar,objlen,1,fout);
|
|
|
9c013b |
|
|
|
9c013b |
if (aobj != sobj)
|
|
|
9c013b |
free(aobj);
|
|
|
9c013b |
|
|
|
9c013b |
if (!vobj)
|
|
|
9c013b |
free(ar);
|
|
|
9c013b |
|
|
|
9c013b |
return (ret == 0)
|
|
|
9c013b |
? MDSO_FILE_ERROR(dctx)
|
|
|
9c013b |
: 0;
|
|
|
9c013b |
}
|