Blame src/internal/perk_hdrdump_impl.c

b73ae8
/***************************************************************/
b73ae8
/*  perk: PE Resource Kit                                      */
b73ae8
/*  Copyright (C) 2015--2017  Z. Gilboa                        */
b73ae8
/*  Released under GPLv2 and GPLv3; see COPYING.PERK.          */
b73ae8
/***************************************************************/
b73ae8
b73ae8
#include <stddef.h>
b73ae8
#include <string.h>
b73ae8
b73ae8
#include <perk/perk.h>
b73ae8
#include "perk_hdrdump_impl.h"
b73ae8
b73ae8
#define PE_TABWIDTH	8
b73ae8
#define PE_HDRSPACE	40
b73ae8
b73ae8
static const char pe_hex_header_hex[] =
b73ae8
	"  0  1  2  3  4  5  6  7    8  9  a  b  c  d  e  f          01234567 89abcdef\n";
b73ae8
b73ae8
static const char pe_hex_header_dot[] =
b73ae8
	" .-------------------------------------------------.       .-----------------.\n";
b73ae8
b73ae8
static const char pe_hex_footer[] =
b73ae8
	"|---------------------------------------------------|      |-----------------|\n\n";
b73ae8
b73ae8
size_t pe_output_hex_header(
b73ae8
	char *		buf,
b73ae8
	const char *	sname,
b73ae8
	uint64_t	faddr,
b73ae8
	uint64_t	vaddr,
b73ae8
	int		bits)
b73ae8
{
b73ae8
	char *		ch;
b73ae8
	size_t		hlen;
b73ae8
	size_t		dlen;
b73ae8
	size_t		slen;
b73ae8
	size_t		nlen;
b73ae8
	uint32_t	high;
b73ae8
	uint32_t	low;
b73ae8
b73ae8
	ch   = buf;
b73ae8
	hlen = strlen(pe_hex_header_hex);
b73ae8
	dlen = strlen(pe_hex_header_dot);
b73ae8
	slen = strlen(sname);
b73ae8
b73ae8
	switch (bits) {
b73ae8
		case 32:
b73ae8
			low  = faddr;
b73ae8
			nlen = sprintf(ch,"faddr: 0x%08x\n",low);
b73ae8
			break;
b73ae8
b73ae8
		case 64:
b73ae8
			low  = faddr;
b73ae8
			high = faddr >> 32;
b73ae8
			nlen = sprintf(ch,"faddr: 0x%08x%08x\n",high,low);
b73ae8
			break;
b73ae8
b73ae8
		default:
b73ae8
			return -1;
b73ae8
	}
b73ae8
b73ae8
	ch += nlen;
b73ae8
b73ae8
	switch (bits) {
b73ae8
		case 32:
b73ae8
			low  = vaddr;
b73ae8
			nlen = sprintf(ch,"vaddr: 0x%08x",low);
b73ae8
			break;
b73ae8
b73ae8
		default:
b73ae8
			low  = vaddr;
b73ae8
			high = vaddr >> 32;
b73ae8
			nlen = sprintf(ch,"vaddr: 0x%08x%08x",high,low);
b73ae8
			break;
b73ae8
	}
b73ae8
b73ae8
	ch += nlen;
b73ae8
	memset(ch,' ',PE_HDRSPACE - nlen);
b73ae8
	ch += PE_HDRSPACE - nlen;
b73ae8
b73ae8
	memcpy(ch,pe_hex_header_hex,hlen);
b73ae8
	ch += hlen;
b73ae8
b73ae8
	memcpy(ch,sname,slen);
b73ae8
b73ae8
	ch += slen;
b73ae8
	memset(ch,' ',PE_HDRSPACE - slen);
b73ae8
	ch += PE_HDRSPACE - slen;
b73ae8
b73ae8
	memcpy(ch,pe_hex_header_dot,dlen);
b73ae8
	ch += dlen;
b73ae8
b73ae8
	return ch - buf;
b73ae8
}
b73ae8
b73ae8
size_t pe_output_hex_footer(char * buf)
b73ae8
{
b73ae8
	size_t	nlen;
b73ae8
b73ae8
	memset(buf,' ',PE_HDRSPACE);
b73ae8
	buf += PE_HDRSPACE;
b73ae8
b73ae8
	nlen = strlen(pe_hex_footer);
b73ae8
	memcpy(buf,pe_hex_footer,nlen);
b73ae8
b73ae8
	return PE_HDRSPACE + nlen;
b73ae8
}
b73ae8
b73ae8
size_t pe_output_raw_element(
b73ae8
	char *		ch,
b73ae8
	const void *	rdata,
b73ae8
	const char *	mname,
b73ae8
	uint32_t	moffset,
b73ae8
	uint32_t	msize)
b73ae8
{
b73ae8
	size_t			nlen;
b73ae8
	char *			base;
b73ae8
	uintptr_t		addr;
b73ae8
	const unsigned char *	src;
b73ae8
	const unsigned char *	cap;
b73ae8
	const unsigned char *	mark;
b73ae8
	size_t			pos;
b73ae8
	size_t			xpos;
b73ae8
	const char		xch[] = "0123456789abcdef";
b73ae8
b73ae8
	/* init */
b73ae8
	base = ch;
b73ae8
b73ae8
	/* pos */
b73ae8
	addr  = (uintptr_t)rdata;
b73ae8
	addr += moffset;
b73ae8
	pos   = addr % 0x10;
b73ae8
	xpos  = pos;
b73ae8
b73ae8
	/* struct member name */
b73ae8
	memset(ch,' ',PE_TABWIDTH);
b73ae8
	ch += PE_TABWIDTH;
b73ae8
b73ae8
	*ch++ = '.';
b73ae8
	nlen = strlen(mname);
b73ae8
	memcpy(ch,mname,nlen);
b73ae8
b73ae8
	ch += nlen;
b73ae8
	*ch++ = ':';
b73ae8
b73ae8
	/* hex dump column */
b73ae8
	nlen  = PE_HDRSPACE - PE_TABWIDTH - nlen - 2;
b73ae8
	memset(ch,' ',nlen);
b73ae8
	ch += nlen;
b73ae8
b73ae8
	*ch++ = '|';
b73ae8
	*ch++ = ' ';
b73ae8
b73ae8
	nlen = 3 * pos;
b73ae8
	memset(ch,' ',nlen);
b73ae8
	ch += nlen;
b73ae8
b73ae8
	if (pos >= 8) {
b73ae8
		*ch++ = ' ';
b73ae8
		*ch++ = ' ';
b73ae8
	}
b73ae8
b73ae8
	/* hex dump */
b73ae8
	src  = rdata;
b73ae8
	src += moffset;
b73ae8
b73ae8
	mark = src;
b73ae8
	cap  = src + msize;
b73ae8
b73ae8
	for (; src
b73ae8
		*ch++ = xch[*src / 0x10];
b73ae8
		*ch++ = xch[*src % 0x10];
b73ae8
		*ch++ = ' ';
b73ae8
b73ae8
		/* pretty columns */
b73ae8
		if (pos == 7) {
b73ae8
			*ch++ = ' ';
b73ae8
			*ch++ = ' ';
b73ae8
		}
b73ae8
b73ae8
		/* binary dump needed? */
b73ae8
		if ((++src == cap) || (pos == 0xf)) {
b73ae8
			/* binary dump column */
b73ae8
			nlen  = 3 * (0xf - pos);
b73ae8
			nlen += (pos < 7) ? 2 : 0;
b73ae8
b73ae8
			memset(ch,' ',nlen);
b73ae8
			ch += nlen;
b73ae8
b73ae8
			*ch++ = '|';
b73ae8
			*ch++ = ' '; *ch++ = ' '; *ch++ = ' ';
b73ae8
			*ch++ = ' '; *ch++ = ' '; *ch++ = ' ';
b73ae8
			*ch++ = '|';
b73ae8
b73ae8
			nlen = xpos + (xpos >= 7);
b73ae8
			memset(ch,' ',nlen);
b73ae8
			ch += nlen;
b73ae8
b73ae8
			/* binary dump */
b73ae8
			for (; mark
b73ae8
				*ch++ = (*mark >= 0x20) && (*mark < 0x7f)
b73ae8
					? *mark : '.';
b73ae8
b73ae8
				/* pretty columns */
b73ae8
				if ((++mark < src) && (++xpos == 8)) {
b73ae8
					*ch++ = ' ';
b73ae8
					xpos  = 0;
b73ae8
				}
b73ae8
			}
b73ae8
b73ae8
			nlen  = 0xf - pos;
b73ae8
			nlen += (pos <= 7);
b73ae8
b73ae8
			memset(ch,' ',nlen);
b73ae8
			ch += nlen;
b73ae8
b73ae8
			*ch++ = '|';
b73ae8
			*ch++ = '\n';
b73ae8
		}
b73ae8
b73ae8
		/* does member hex dump span across more than one line? */
b73ae8
		if ((src < cap) && (++pos == 0x10)) {
b73ae8
			memset(ch,' ',PE_HDRSPACE);
b73ae8
			ch += PE_HDRSPACE;
b73ae8
			*ch++ = '|';
b73ae8
			*ch++ = ' ';
b73ae8
b73ae8
			mark = src;
b73ae8
			pos  = 0;
b73ae8
			xpos = 0;
b73ae8
		}
b73ae8
	}
b73ae8
b73ae8
	return ch - base;
b73ae8
}