|
|
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>
|
|
|
d6e02b |
#include <perk/perk_consts.h>
|
|
|
d6e02b |
#include <perk/perk_structs.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 |
}
|