Blame src/output/pe_output_mdso_libraries.c

c63b6d
/***************************************************************/
c63b6d
/*  perk: PE Resource Kit                                      */
c63b6d
/*  Copyright (C) 2015--2017  Z. Gilboa                        */
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>
c63b6d
#include <perk/perk_output.h>
c63b6d
#include "perk_reader_impl.h"
c63b6d
#include "perk_errinfo_impl.h"
c63b6d
c63b6d
static int pretty_header(const struct pe_common_ctx * cctx, FILE * fout)
c63b6d
{
c63b6d
	return (cctx->fmtflags & PERK_PRETTY_YAML)
c63b6d
		? fputs("dsolibs:\n",fout)
c63b6d
		: 0;
c63b6d
}
c63b6d
c63b6d
static int pretty_dsolib_header(const struct pe_common_ctx * cctx, const char * name, FILE * fout)
c63b6d
{
c63b6d
	if ((cctx->fmtflags & PERK_PRETTY_YAML) && (cctx->fmtflags & PERK_OUTPUT_MDSO_SYMS))
c63b6d
		return fprintf(fout,"  %s:\n",name);
c63b6d
	else if (cctx->fmtflags & PERK_PRETTY_YAML)
c63b6d
		return fprintf(fout,"- %s:\n",name);
c63b6d
	else if (cctx->fmtflags & PERK_OUTPUT_MDSO_SYMS)
c63b6d
		return fprintf(fout,"%s:\n",name);
c63b6d
	else
c63b6d
		return fprintf(fout,"%s\n",name);
c63b6d
}
c63b6d
c63b6d
static int pretty_dsolib_item(const struct pe_common_ctx * cctx, const char * name, FILE * fout)
c63b6d
{
c63b6d
	if (cctx->fmtflags & PERK_PRETTY_YAML)
c63b6d
		return fprintf(fout,"  - %s\n",name);
c63b6d
	else
c63b6d
		return fprintf(fout,"%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;
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
c63b6d
	return m->r_image.map_addr + roffset;
c63b6d
}
c63b6d
c63b6d
static unsigned char * dsosym_meta(const struct pe_image_meta * m, int j)
c63b6d
{
c63b6d
	uintptr_t			va;
c63b6d
	uint64_t			rva;
c63b6d
	uint32_t			roffset;
c63b6d
	struct mdso_raw_sym_entry_m32 *	sym32;
c63b6d
	struct mdso_raw_sym_entry_m64 *	sym64;
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);
c63b6d
		rva   = va - m->m_opt.oh_mem.coh_image_base;
c63b6d
c63b6d
		if (rva >> 32)
c63b6d
			return 0;
c63b6d
	} else {
c63b6d
		sym32 = (struct mdso_raw_sym_entry_m32 *)m->r_dsosyms + j;
c63b6d
		va    = pe_read_long(sym32->msym_meta);
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
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
{
c63b6d
	uintptr_t			va;
c63b6d
	uint64_t			rva;
c63b6d
	uint32_t			roffset;
c63b6d
	struct mdso_raw_sym_entry_m32 *	sym32;
c63b6d
	struct mdso_raw_sym_entry_m64 *	sym64;
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);
c63b6d
		rva   = va - m->m_opt.oh_mem.coh_image_base;
c63b6d
c63b6d
		if (rva >> 32)
c63b6d
			return 0;
c63b6d
	} else {
c63b6d
		sym32 = (struct mdso_raw_sym_entry_m32 *)m->r_dsosyms + j;
c63b6d
		va    = pe_read_long(sym32->msym_string);
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
c63b6d
	return m->r_image.map_addr + roffset;
c63b6d
}
c63b6d
c63b6d
int pe_output_mdso_libraries(
c63b6d
	const struct pe_driver_ctx *	dctx,
c63b6d
	const struct pe_image_meta *	m,
c63b6d
	FILE *				fout)
c63b6d
{
c63b6d
	int				i,j;
c63b6d
	char *				name;
c63b6d
	unsigned char *			symmeta;
c63b6d
	unsigned char *			dsometa;
c63b6d
	char *				symstr;
c63b6d
	const struct pe_common_ctx *	cctx = dctx->cctx;
c63b6d
c63b6d
	if (!m->m_stats.t_ndsolibs)
c63b6d
		return 0;
c63b6d
c63b6d
	if (!fout)
c63b6d
		fout = stdout;
c63b6d
c63b6d
	if (pe_get_image_abi(m,0) == PE_ABI_UNSUPPORTED)
c63b6d
		return PERK_CUSTOM_ERROR(
c63b6d
			dctx,PERK_ERR_UNSUPPORTED_ABI);
c63b6d
c63b6d
	if ((pretty_header(cctx,fout)) < 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
c63b6d
		if ((pretty_dsolib_header(cctx,name,fout)) < 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)
c63b6d
					if ((pretty_dsolib_item(cctx,symstr,fout)) < 0)
c63b6d
						return PERK_FILE_ERROR(dctx);
c63b6d
			}
c63b6d
		}
c63b6d
	}
c63b6d
c63b6d
	return 0;
c63b6d
}