diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/internal/perk_hdrdump_impl.c | 234 | ||||
-rw-r--r-- | src/internal/perk_hdrdump_impl.h | 49 |
2 files changed, 283 insertions, 0 deletions
diff --git a/src/internal/perk_hdrdump_impl.c b/src/internal/perk_hdrdump_impl.c new file mode 100644 index 0000000..eadd725 --- /dev/null +++ b/src/internal/perk_hdrdump_impl.c @@ -0,0 +1,234 @@ +/***************************************************************/ +/* perk: PE Resource Kit */ +/* Copyright (C) 2015--2017 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.PERK. */ +/***************************************************************/ + +#include <stddef.h> +#include <string.h> + +#include <perk/perk.h> +#include "perk_hdrdump_impl.h" + +#define PE_TABWIDTH 8 +#define PE_HDRSPACE 40 + +static const char pe_hex_header_hex[] = + " 0 1 2 3 4 5 6 7 8 9 a b c d e f 01234567 89abcdef\n"; + +static const char pe_hex_header_dot[] = + " .-------------------------------------------------. .-----------------.\n"; + +static const char pe_hex_footer[] = + "|---------------------------------------------------| |-----------------|\n\n"; + +size_t pe_output_hex_header( + char * buf, + const char * sname, + uint64_t faddr, + uint64_t vaddr, + int bits) +{ + char * ch; + size_t hlen; + size_t dlen; + size_t slen; + size_t nlen; + uint32_t high; + uint32_t low; + + ch = buf; + hlen = strlen(pe_hex_header_hex); + dlen = strlen(pe_hex_header_dot); + slen = strlen(sname); + + switch (bits) { + case 32: + low = faddr; + nlen = sprintf(ch,"faddr: 0x%08x\n",low); + break; + + case 64: + low = faddr; + high = faddr >> 32; + nlen = sprintf(ch,"faddr: 0x%08x%08x\n",high,low); + break; + + default: + return -1; + } + + ch += nlen; + + switch (bits) { + case 32: + low = vaddr; + nlen = sprintf(ch,"vaddr: 0x%08x",low); + break; + + default: + low = vaddr; + high = vaddr >> 32; + nlen = sprintf(ch,"vaddr: 0x%08x%08x",high,low); + break; + } + + ch += nlen; + memset(ch,' ',PE_HDRSPACE - nlen); + ch += PE_HDRSPACE - nlen; + + memcpy(ch,pe_hex_header_hex,hlen); + ch += hlen; + + memcpy(ch,sname,slen); + + ch += slen; + memset(ch,' ',PE_HDRSPACE - slen); + ch += PE_HDRSPACE - slen; + + memcpy(ch,pe_hex_header_dot,dlen); + ch += dlen; + + return ch - buf; +} + +size_t pe_output_hex_footer(char * buf) +{ + size_t nlen; + + memset(buf,' ',PE_HDRSPACE); + buf += PE_HDRSPACE; + + nlen = strlen(pe_hex_footer); + memcpy(buf,pe_hex_footer,nlen); + + return PE_HDRSPACE + nlen; +} + +size_t pe_output_raw_element( + char * ch, + const void * rdata, + const char * mname, + uint32_t moffset, + uint32_t msize) +{ + size_t nlen; + char * base; + uintptr_t addr; + const unsigned char * src; + const unsigned char * cap; + const unsigned char * mark; + size_t pos; + size_t xpos; + const char xch[] = "0123456789abcdef"; + + /* init */ + base = ch; + + /* pos */ + addr = (uintptr_t)rdata; + addr += moffset; + pos = addr % 0x10; + xpos = pos; + + /* struct member name */ + memset(ch,' ',PE_TABWIDTH); + ch += PE_TABWIDTH; + + *ch++ = '.'; + nlen = strlen(mname); + memcpy(ch,mname,nlen); + + ch += nlen; + *ch++ = ':'; + + /* hex dump column */ + nlen = PE_HDRSPACE - PE_TABWIDTH - nlen - 2; + memset(ch,' ',nlen); + ch += nlen; + + *ch++ = '|'; + *ch++ = ' '; + + nlen = 3 * pos; + memset(ch,' ',nlen); + ch += nlen; + + if (pos >= 8) { + *ch++ = ' '; + *ch++ = ' '; + } + + /* hex dump */ + src = rdata; + src += moffset; + + mark = src; + cap = src + msize; + + for (; src<cap; ) { + *ch++ = xch[*src / 0x10]; + *ch++ = xch[*src % 0x10]; + *ch++ = ' '; + + /* pretty columns */ + if (pos == 7) { + *ch++ = ' '; + *ch++ = ' '; + } + + /* binary dump needed? */ + if ((++src == cap) || (pos == 0xf)) { + /* binary dump column */ + nlen = 3 * (0xf - pos); + nlen += (pos < 7) ? 2 : 0; + + memset(ch,' ',nlen); + ch += nlen; + + *ch++ = '|'; + *ch++ = ' '; *ch++ = ' '; *ch++ = ' '; + *ch++ = ' '; *ch++ = ' '; *ch++ = ' '; + *ch++ = '|'; + + nlen = xpos + (xpos >= 7); + memset(ch,' ',nlen); + ch += nlen; + + /* binary dump */ + for (; mark<src; ) { + *ch++ = (*mark >= 0x20) && (*mark < 0x7f) + ? *mark : '.'; + + /* pretty columns */ + if ((++mark < src) && (++xpos == 8)) { + *ch++ = ' '; + xpos = 0; + } + } + + nlen = 0xf - pos; + nlen += (pos <= 7); + + memset(ch,' ',nlen); + ch += nlen; + + *ch++ = '|'; + *ch++ = '\n'; + } + + /* does member hex dump span across more than one line? */ + if ((src < cap) && (++pos == 0x10)) { + memset(ch,' ',PE_HDRSPACE); + ch += PE_HDRSPACE; + *ch++ = '|'; + *ch++ = ' '; + + mark = src; + pos = 0; + xpos = 0; + } + } + + return ch - base; +} diff --git a/src/internal/perk_hdrdump_impl.h b/src/internal/perk_hdrdump_impl.h new file mode 100644 index 0000000..41528ad --- /dev/null +++ b/src/internal/perk_hdrdump_impl.h @@ -0,0 +1,49 @@ +/***************************************************************/ +/* perk: PE Resource Kit */ +/* Copyright (C) 2015--2018 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.PERK. */ +/***************************************************************/ + +#ifndef PERK_HDRDUMP_IMPL_H +#define PERK_HDRDUMP_IMPL_H + +#include <stddef.h> + +#define PE_QUOTE(s) #s +#define PE_STRING(s) PE_QUOTE(s) +#define PE_TYPE(t) struct pe_raw_ ## t +#define PE_OFFSET(t,x) offsetof(PE_TYPE(t),x) +#define PE_SIZE(p,x) sizeof((p)->x) + +#define PE_OUTPUT_RAW_ELEMENT_TABLE(ch,p,t,x) \ + pe_output_raw_element( \ + ch,p, \ + PE_STRING(x), \ + PE_OFFSET(t,x), \ + PE_SIZE(p,x)) + +#define PE_OUTPUT_TABLE(x) \ + PE_OUTPUT_RAW_ELEMENT_TABLE( \ + ch, \ + PE_ADDR, \ + PE_RAW_STRUCT, \ + x) + +size_t pe_output_hex_header( + char * buf, + const char * sname, + uint64_t faddr, + uint64_t vaddr, + int bits); + +size_t pe_output_hex_footer( + char * buf); + +size_t pe_output_raw_element( + char * ch, + const void * rdata, + const char * mname, + uint32_t moffset, + uint32_t msize); + +#endif |