|
|
c63b6d |
/***************************************************************/
|
|
|
c63b6d |
/* perk: PE Resource Kit */
|
|
|
425fb8 |
/* Copyright (C) 2015--2021 SysDeer Technologies, LLC */
|
|
|
c63b6d |
/* Released under GPLv2 and GPLv3; see COPYING.PERK. */
|
|
|
c63b6d |
/***************************************************************/
|
|
|
c63b6d |
|
|
|
c63b6d |
#include <stdint.h>
|
|
|
c63b6d |
#include <stdlib.h>
|
|
|
c63b6d |
#include <stdio.h>
|
|
|
c63b6d |
#include <string.h>
|
|
|
c63b6d |
#include <errno.h>
|
|
|
c63b6d |
|
|
|
c63b6d |
#include <mdso/mdso_specs.h>
|
|
|
c63b6d |
#include <mdso/mdso_structs.h>
|
|
|
c63b6d |
|
|
|
c63b6d |
#include <perk/perk.h>
|
|
|
d6e02b |
#include <perk/perk_consts.h>
|
|
|
c63b6d |
#include <perk/perk_output.h>
|
|
|
c63b6d |
#include "perk_reader_impl.h"
|
|
|
67bba7 |
#include "perk_driver_impl.h"
|
|
|
67bba7 |
#include "perk_dprintf_impl.h"
|
|
|
c63b6d |
#include "perk_errinfo_impl.h"
|
|
|
c63b6d |
|
|
|
67bba7 |
static int pretty_header(
|
|
|
67bba7 |
int fdout,
|
|
|
67bba7 |
const struct pe_common_ctx * cctx)
|
|
|
c63b6d |
{
|
|
|
c63b6d |
return (cctx->fmtflags & PERK_PRETTY_YAML)
|
|
|
67bba7 |
? pe_dprintf(fdout,"dsolibs:\n")
|
|
|
c63b6d |
: 0;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
67bba7 |
static int pretty_dsolib_header(
|
|
|
67bba7 |
int fdout,
|
|
|
67bba7 |
const struct pe_common_ctx * cctx,
|
|
|
67bba7 |
const char * name)
|
|
|
c63b6d |
{
|
|
|
c63b6d |
if ((cctx->fmtflags & PERK_PRETTY_YAML) && (cctx->fmtflags & PERK_OUTPUT_MDSO_SYMS))
|
|
|
67bba7 |
return pe_dprintf(fdout," %s:\n",name);
|
|
|
c63b6d |
else if (cctx->fmtflags & PERK_PRETTY_YAML)
|
|
|
67bba7 |
return pe_dprintf(fdout,"- %s:\n",name);
|
|
|
c63b6d |
else if (cctx->fmtflags & PERK_OUTPUT_MDSO_SYMS)
|
|
|
67bba7 |
return pe_dprintf(fdout,"%s:\n",name);
|
|
|
c63b6d |
else
|
|
|
67bba7 |
return pe_dprintf(fdout,"%s\n",name);
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
67bba7 |
static int pretty_dsolib_item(
|
|
|
67bba7 |
int fdout,
|
|
|
67bba7 |
const struct pe_common_ctx * cctx,
|
|
|
67bba7 |
const char * name)
|
|
|
c63b6d |
{
|
|
|
c63b6d |
if (cctx->fmtflags & PERK_PRETTY_YAML)
|
|
|
67bba7 |
return pe_dprintf(fdout," - %s\n",name);
|
|
|
c63b6d |
else
|
|
|
67bba7 |
return pe_dprintf(fdout,"%s\n",name);
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
static unsigned char * dsolib_meta(const struct pe_image_meta * m, int i)
|
|
|
c63b6d |
{
|
|
|
c63b6d |
struct mdso_raw_meta_record_m32 * mdso32;
|
|
|
c63b6d |
struct mdso_raw_meta_record_m64 * mdso64;
|
|
|
c63b6d |
|
|
|
c63b6d |
if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) {
|
|
|
c63b6d |
mdso64 = (struct mdso_raw_meta_record_m64 *)m->r_dsometa + i;
|
|
|
c63b6d |
return mdso64->mrec_base;
|
|
|
c63b6d |
} else {
|
|
|
c63b6d |
mdso32 = (struct mdso_raw_meta_record_m32 *)m->r_dsometa + i;
|
|
|
c63b6d |
return mdso32->mrec_base;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
static char * dsolib_name(const struct pe_image_meta * m, int i)
|
|
|
c63b6d |
{
|
|
|
c63b6d |
uintptr_t va;
|
|
|
c63b6d |
uint64_t rva;
|
|
|
caef10 |
char * addr;
|
|
|
c63b6d |
uint32_t roffset;
|
|
|
c63b6d |
struct mdso_raw_meta_record_m32 * mdso32;
|
|
|
c63b6d |
struct mdso_raw_meta_record_m64 * mdso64;
|
|
|
c63b6d |
|
|
|
c63b6d |
if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) {
|
|
|
c63b6d |
mdso64 = (struct mdso_raw_meta_record_m64 *)m->r_dsometa + i;
|
|
|
c63b6d |
va = pe_read_quad(mdso64->mrec_name);
|
|
|
c63b6d |
rva = va - m->m_opt.oh_mem.coh_image_base;
|
|
|
c63b6d |
|
|
|
c63b6d |
if (rva >> 32)
|
|
|
c63b6d |
return 0;
|
|
|
c63b6d |
} else {
|
|
|
c63b6d |
mdso32 = (struct mdso_raw_meta_record_m32 *)m->r_dsometa + i;
|
|
|
c63b6d |
va = pe_read_long(mdso32->mrec_name);
|
|
|
c63b6d |
rva = va - m->m_opt.oh_mem.coh_image_base;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
if (pe_get_roffset_from_rva(m,(uint32_t)rva,&roffset) < 0)
|
|
|
c63b6d |
return 0;
|
|
|
c63b6d |
|
|
|
caef10 |
return (addr = m->r_image.map_addr) + roffset;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
static unsigned char * dsosym_meta(const struct pe_image_meta * m, int j)
|
|
|
c63b6d |
{
|
|
|
a4a68a |
uint64_t va;
|
|
|
a4a68a |
uint32_t rva;
|
|
|
c63b6d |
uint32_t roffset;
|
|
|
c63b6d |
struct mdso_raw_sym_entry_m32 * sym32;
|
|
|
c63b6d |
struct mdso_raw_sym_entry_m64 * sym64;
|
|
|
a4a68a |
int idx;
|
|
|
c63b6d |
|
|
|
c63b6d |
if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) {
|
|
|
c63b6d |
sym64 = (struct mdso_raw_sym_entry_m64 *)m->r_dsosyms + j;
|
|
|
c63b6d |
va = pe_read_quad(sym64->msym_meta);
|
|
|
a4a68a |
rva = pe_read_long(sym64->msym_meta);
|
|
|
c63b6d |
} else {
|
|
|
c63b6d |
sym32 = (struct mdso_raw_sym_entry_m32 *)m->r_dsosyms + j;
|
|
|
c63b6d |
va = pe_read_long(sym32->msym_meta);
|
|
|
a4a68a |
rva = va;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
a4a68a |
if ((idx = pe_get_named_section_index(m,MDSO_META_SECTION)) >= 0)
|
|
|
a4a68a |
if (idx != pe_get_block_section_index(m,&(struct pe_block){rva,0}))
|
|
|
a4a68a |
return (unsigned char *)(-1);
|
|
|
a4a68a |
|
|
|
a4a68a |
if (va > rva)
|
|
|
a4a68a |
return 0;
|
|
|
a4a68a |
|
|
|
a4a68a |
if (pe_get_roffset_from_rva(m,rva,&roffset) < 0)
|
|
|
c63b6d |
return 0;
|
|
|
c63b6d |
|
|
|
c63b6d |
return (unsigned char *)m->r_image.map_addr + roffset;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
static char * dsosym_string(const struct pe_image_meta * m, int j)
|
|
|
c63b6d |
{
|
|
|
a4a68a |
uint64_t va;
|
|
|
a4a68a |
uint32_t rva;
|
|
|
caef10 |
char * addr;
|
|
|
c63b6d |
uint32_t roffset;
|
|
|
c63b6d |
struct mdso_raw_sym_entry_m32 * sym32;
|
|
|
c63b6d |
struct mdso_raw_sym_entry_m64 * sym64;
|
|
|
a4a68a |
int idx;
|
|
|
c63b6d |
|
|
|
c63b6d |
if (m->m_opt.oh_std.coh_magic == PE_MAGIC_PE32_PLUS) {
|
|
|
c63b6d |
sym64 = (struct mdso_raw_sym_entry_m64 *)m->r_dsosyms + j;
|
|
|
c63b6d |
va = pe_read_quad(sym64->msym_string);
|
|
|
a4a68a |
rva = pe_read_long(sym64->msym_string);
|
|
|
c63b6d |
} else {
|
|
|
c63b6d |
sym32 = (struct mdso_raw_sym_entry_m32 *)m->r_dsosyms + j;
|
|
|
c63b6d |
va = pe_read_long(sym32->msym_string);
|
|
|
a4a68a |
rva = va;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
a4a68a |
if ((idx = pe_get_named_section_index(m,MDSO_STRS_SECTION)) >= 0)
|
|
|
a4a68a |
if (idx != pe_get_block_section_index(m,&(struct pe_block){rva,0}))
|
|
|
a4a68a |
return (char *)(-2);
|
|
|
a4a68a |
|
|
|
a4a68a |
if (va > rva)
|
|
|
a4a68a |
return 0;
|
|
|
a4a68a |
|
|
|
a4a68a |
if (pe_get_roffset_from_rva(m,rva,&roffset) < 0)
|
|
|
c63b6d |
return 0;
|
|
|
c63b6d |
|
|
|
caef10 |
return (addr = m->r_image.map_addr) + roffset;
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
int pe_output_mdso_libraries(
|
|
|
c63b6d |
const struct pe_driver_ctx * dctx,
|
|
|
67bba7 |
const struct pe_image_meta * m)
|
|
|
c63b6d |
{
|
|
|
c63b6d |
int i,j;
|
|
|
67bba7 |
int fdout;
|
|
|
c63b6d |
char * name;
|
|
|
c63b6d |
unsigned char * symmeta;
|
|
|
c63b6d |
unsigned char * dsometa;
|
|
|
c63b6d |
char * symstr;
|
|
|
c63b6d |
const struct pe_common_ctx * cctx = dctx->cctx;
|
|
|
c63b6d |
|
|
|
67bba7 |
fdout = pe_driver_fdout(dctx);
|
|
|
67bba7 |
|
|
|
c63b6d |
if (!m->m_stats.t_ndsolibs)
|
|
|
c63b6d |
return 0;
|
|
|
c63b6d |
|
|
|
c63b6d |
if (pe_get_image_abi(m,0) == PE_ABI_UNSUPPORTED)
|
|
|
c63b6d |
return PERK_CUSTOM_ERROR(
|
|
|
c63b6d |
dctx,PERK_ERR_UNSUPPORTED_ABI);
|
|
|
c63b6d |
|
|
|
67bba7 |
if ((pretty_header(fdout,cctx)) < 0)
|
|
|
c63b6d |
return PERK_FILE_ERROR(dctx);
|
|
|
c63b6d |
|
|
|
c63b6d |
for (i=0; i<m->m_stats.t_ndsolibs; i++) {
|
|
|
c63b6d |
dsometa = dsolib_meta(m,i);
|
|
|
c63b6d |
|
|
|
c63b6d |
if (!(name = dsolib_name(m,i)))
|
|
|
c63b6d |
return PERK_CUSTOM_ERROR(
|
|
|
c63b6d |
dctx,PERK_ERR_IMAGE_MALFORMED);
|
|
|
c63b6d |
|
|
|
67bba7 |
if ((pretty_dsolib_header(fdout,cctx,name)) < 0)
|
|
|
c63b6d |
return PERK_FILE_ERROR(dctx);
|
|
|
c63b6d |
|
|
|
c63b6d |
if (cctx->fmtflags & PERK_OUTPUT_MDSO_SYMS) {
|
|
|
c63b6d |
for (j=0; j<m->m_stats.t_ndsosyms; j++) {
|
|
|
c63b6d |
if (!(symmeta = dsosym_meta(m,j)))
|
|
|
c63b6d |
return PERK_CUSTOM_ERROR(
|
|
|
c63b6d |
dctx,PERK_ERR_IMAGE_MALFORMED);
|
|
|
c63b6d |
|
|
|
c63b6d |
if (!(symstr = dsosym_string(m,j)))
|
|
|
c63b6d |
return PERK_CUSTOM_ERROR(
|
|
|
c63b6d |
dctx,PERK_ERR_IMAGE_MALFORMED);
|
|
|
c63b6d |
|
|
|
c63b6d |
if (symmeta == dsometa)
|
|
|
67bba7 |
if ((pretty_dsolib_item(fdout,cctx,symstr)) < 0)
|
|
|
c63b6d |
return PERK_FILE_ERROR(dctx);
|
|
|
c63b6d |
}
|
|
|
c63b6d |
}
|
|
|
c63b6d |
}
|
|
|
c63b6d |
|
|
|
c63b6d |
return 0;
|
|
|
c63b6d |
}
|