Blame src/output/pe_output_mdso_libraries.c

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
}