|
Packit |
d4ea60 |
/*
|
|
Packit |
d4ea60 |
* This is modified version of Simple PT dumper by Andi Kleen
|
|
Packit |
d4ea60 |
* https://github.com/andikleen/simple-pt
|
|
Packit |
d4ea60 |
*/
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
/*
|
|
Packit |
d4ea60 |
* Copyright (c) 2015, Intel Corporation
|
|
Packit |
d4ea60 |
* Author: Andi Kleen
|
|
Packit |
d4ea60 |
* All rights reserved.
|
|
Packit |
d4ea60 |
*
|
|
Packit |
d4ea60 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
d4ea60 |
* modification, are permitted provided that the following conditions are met:
|
|
Packit |
d4ea60 |
*
|
|
Packit |
d4ea60 |
* 1. Redistributions of source code must retain the above copyright notice,
|
|
Packit |
d4ea60 |
* this list of conditions and the following disclaimer.
|
|
Packit |
d4ea60 |
*
|
|
Packit |
d4ea60 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit |
d4ea60 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit |
d4ea60 |
* documentation and/or other materials provided with the distribution.
|
|
Packit |
d4ea60 |
*
|
|
Packit |
d4ea60 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
Packit |
d4ea60 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
Packit |
d4ea60 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
|
Packit |
d4ea60 |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
|
Packit |
d4ea60 |
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
|
Packit |
d4ea60 |
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
Packit |
d4ea60 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
Packit |
d4ea60 |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit |
d4ea60 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
Packit |
d4ea60 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
Packit |
d4ea60 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
|
Packit |
d4ea60 |
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
Packit |
d4ea60 |
*/
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
#define _GNU_SOURCE 1
|
|
Packit |
d4ea60 |
#include <sys/mman.h>
|
|
Packit |
d4ea60 |
#include <sys/fcntl.h>
|
|
Packit |
d4ea60 |
#include <sys/stat.h>
|
|
Packit |
d4ea60 |
#include <stdio.h>
|
|
Packit |
d4ea60 |
#include <stdlib.h>
|
|
Packit |
d4ea60 |
#include <string.h>
|
|
Packit |
d4ea60 |
#include <stdint.h>
|
|
Packit |
d4ea60 |
#include <unistd.h>
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
#include "defs.h"
|
|
Packit |
d4ea60 |
#include "map.h"
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
#define BIT(x) (1U << (x))
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
typedef unsigned long long u64;
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static FILE *out_fp;
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static char psb[16] = {
|
|
Packit |
d4ea60 |
0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82,
|
|
Packit |
d4ea60 |
0x02, 0x82, 0x02, 0x82, 0x02, 0x82, 0x02, 0x82
|
|
Packit |
d4ea60 |
};
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
#define LEFT(x) ((end - p) >= (x))
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
/* Caller must have checked length */
|
|
Packit |
d4ea60 |
static u64 get_ip_val(unsigned char **pp, unsigned char *end, int len, uint64_t *last_ip)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
unsigned char *p = *pp;
|
|
Packit |
d4ea60 |
u64 v = *last_ip;
|
|
Packit |
d4ea60 |
int i;
|
|
Packit |
d4ea60 |
unsigned shift = 0;
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
if (len == 0) {
|
|
Packit |
d4ea60 |
*last_ip = 0;
|
|
Packit |
d4ea60 |
return 0; /* out of context */
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (len < 4) {
|
|
Packit |
d4ea60 |
if (!LEFT(len)) {
|
|
Packit |
d4ea60 |
*last_ip = 0;
|
|
Packit |
d4ea60 |
return 0; /* XXX error */
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
for (i = 0; i < len; i++, shift += 16, p += 2) {
|
|
Packit |
d4ea60 |
uint64_t b = *(uint16_t *)p;
|
|
Packit |
d4ea60 |
v = (v & ~(0xffffULL << shift)) | (b << shift);
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
v = ((int64_t)(v << (64 - 48))) >> (64 - 48); /* sign extension */
|
|
Packit |
d4ea60 |
} else {
|
|
Packit |
d4ea60 |
return 0; /* XXX error */
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
*pp = p;
|
|
Packit |
d4ea60 |
*last_ip = v;
|
|
Packit |
d4ea60 |
return v;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static char *get_ip_symbol(u64 ip, char *buf, int bufsize)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
struct syment *sm;
|
|
Packit |
d4ea60 |
ulong offset;
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
sm = value_search(ip, &offset);
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
if (sm) {
|
|
Packit |
d4ea60 |
if (!offset)
|
|
Packit |
d4ea60 |
sprintf(buf, "%s", sm->name);
|
|
Packit |
d4ea60 |
else
|
|
Packit |
d4ea60 |
sprintf(buf, "%s+%lu", sm->name, offset);
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
return buf;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
return NULL;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
/* Caller must have checked length */
|
|
Packit |
d4ea60 |
static u64 get_val(unsigned char **pp, int len)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
unsigned char *p = *pp;
|
|
Packit |
d4ea60 |
u64 v = 0;
|
|
Packit |
d4ea60 |
int i;
|
|
Packit |
d4ea60 |
unsigned shift = 0;
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
for (i = 0; i < len; i++, shift += 8)
|
|
Packit |
d4ea60 |
v |= ((uint64_t)(*p++)) << shift;
|
|
Packit |
d4ea60 |
*pp = p;
|
|
Packit |
d4ea60 |
return v;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static void print_unknown(unsigned char *p, unsigned char *end, unsigned char *map)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
fprintf(out_fp, "unknown packet: ");
|
|
Packit |
d4ea60 |
unsigned len = end - p;
|
|
Packit |
d4ea60 |
int i;
|
|
Packit |
d4ea60 |
if (len > 16)
|
|
Packit |
d4ea60 |
len = 16;
|
|
Packit |
d4ea60 |
for (i = 0; i < len; i++)
|
|
Packit |
d4ea60 |
fprintf(out_fp, "%02x ", p[i]);
|
|
Packit |
d4ea60 |
fprintf(out_fp, "\n");
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static void print_tnt_byte(unsigned char v, int max)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
int i;
|
|
Packit |
d4ea60 |
for (i = max - 1; i >= 0; i--)
|
|
Packit |
d4ea60 |
if (v & BIT(i))
|
|
Packit |
d4ea60 |
fprintf(out_fp, "T");
|
|
Packit |
d4ea60 |
else
|
|
Packit |
d4ea60 |
fprintf(out_fp, "N");
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static void print_tnt_stop(unsigned char v)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
int j;
|
|
Packit |
d4ea60 |
for (j = 7; j >= 0; j--) {
|
|
Packit |
d4ea60 |
if (v & BIT(j))
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
print_tnt_byte(v, j);
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
static void print_multi_tnt(unsigned char *p, int len)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
int i;
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
for (i = len - 1; i >= 0 && p[i] == 0; i--)
|
|
Packit |
d4ea60 |
;
|
|
Packit |
d4ea60 |
if (i >= 0) {
|
|
Packit |
d4ea60 |
print_tnt_stop(p[i]);
|
|
Packit |
d4ea60 |
i--;
|
|
Packit |
d4ea60 |
} else {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "??? no stop bit");
|
|
Packit |
d4ea60 |
return;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
for (; i >= 0; i--)
|
|
Packit |
d4ea60 |
print_tnt_byte(p[i], 8);
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
void decode_buffer(unsigned char *map, size_t len)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
unsigned char *end = map + len;
|
|
Packit |
d4ea60 |
unsigned char *p;
|
|
Packit |
d4ea60 |
size_t skipped = 0;
|
|
Packit |
d4ea60 |
size_t overflow = 0;
|
|
Packit |
d4ea60 |
uint64_t last_ip = 0;
|
|
Packit |
d4ea60 |
u64 ip;
|
|
Packit |
d4ea60 |
char buf[64];
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
for (p = map; p < end; ) {
|
|
Packit |
d4ea60 |
unsigned char *prev = p;
|
|
Packit |
d4ea60 |
/* look for PSB */
|
|
Packit |
d4ea60 |
p = memmem(p, end - p, psb, 16);
|
|
Packit |
d4ea60 |
if (!p) {
|
|
Packit |
d4ea60 |
p = end;
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
skipped += p - prev;
|
|
Packit |
d4ea60 |
while (p < end) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "%lx\t", p - map);
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
if (*p == 2 && LEFT(2)) {
|
|
Packit |
d4ea60 |
if (p[1] == 0xa3 && LEFT(8)) { /* long TNT */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "tnt64 ");
|
|
Packit |
d4ea60 |
print_multi_tnt(p + 2, 6);
|
|
Packit |
d4ea60 |
fprintf(out_fp, "\n");
|
|
Packit |
d4ea60 |
p += 8;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p[1] == 0x43 && LEFT(8)) { /* PIP */
|
|
Packit |
d4ea60 |
p += 2;
|
|
Packit |
d4ea60 |
fprintf(out_fp, "pip\t%llx\n", (get_val(&p, 6) >> 1) << 5);
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p[1] == 3 && LEFT(4) && p[3] == 0) { /* CBR */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "cbr\t%u\n", p[2]);
|
|
Packit |
d4ea60 |
p += 4;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p[1] == 0b10000011) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "tracestop\n");
|
|
Packit |
d4ea60 |
p += 2;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p[1] == 0b11110011 && LEFT(8)) { /* OVF */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "ovf\n");
|
|
Packit |
d4ea60 |
p += 8;
|
|
Packit |
d4ea60 |
overflow++;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p[1] == 0x82 && LEFT(16) && !memcmp(p, psb, 16)) { /* PSB */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "psb\n");
|
|
Packit |
d4ea60 |
p += 16;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p[1] == 0b100011) { /* PSBEND */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "psbend\n");
|
|
Packit |
d4ea60 |
p += 2;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
/* MNT */
|
|
Packit |
d4ea60 |
if (p[1] == 0b11000011 && LEFT(11) && p[2] == 0b10001000) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "mnt\t%llx\n",
|
|
Packit |
d4ea60 |
p[3] |
|
|
Packit |
d4ea60 |
((u64)p[4] << 8) |
|
|
Packit |
d4ea60 |
((u64)p[5] << 16) |
|
|
Packit |
d4ea60 |
((u64)p[6] << 24) |
|
|
Packit |
d4ea60 |
((u64)p[7] << 32) |
|
|
Packit |
d4ea60 |
((u64)p[8] << 40) |
|
|
Packit |
d4ea60 |
((u64)p[9] << 48) |
|
|
Packit |
d4ea60 |
((u64)p[10] << 56));
|
|
Packit |
d4ea60 |
p += 10;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
/* TMA */
|
|
Packit |
d4ea60 |
if (p[1] == 0b01110011 && LEFT(7)) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "tma\tctc=%u fc=%u\n",
|
|
Packit |
d4ea60 |
p[2] | (p[3] << 8),
|
|
Packit |
d4ea60 |
p[5] | ((p[6] & 1) << 8));
|
|
Packit |
d4ea60 |
p += 7;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
/* VMCS */
|
|
Packit |
d4ea60 |
if (p[1] == 0b11001000 && LEFT(7)) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "vmcs\t%llx\n",
|
|
Packit |
d4ea60 |
((u64)p[2] << 12) |
|
|
Packit |
d4ea60 |
((u64)p[3] << 20) |
|
|
Packit |
d4ea60 |
((u64)p[4] << 28) |
|
|
Packit |
d4ea60 |
((u64)p[5] << 36) |
|
|
Packit |
d4ea60 |
((u64)p[6] << 44));
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
if ((*p & BIT(0)) == 0) {
|
|
Packit |
d4ea60 |
if (*p == 0) { /* PAD */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "pad\n");
|
|
Packit |
d4ea60 |
p++;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
fprintf(out_fp, "tnt8 ");
|
|
Packit |
d4ea60 |
print_tnt_stop(*p >> 1);
|
|
Packit |
d4ea60 |
fprintf(out_fp, "\n");
|
|
Packit |
d4ea60 |
p++;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
char *name = NULL;
|
|
Packit |
d4ea60 |
switch (*p & 0x1f) {
|
|
Packit |
d4ea60 |
case 0xd:
|
|
Packit |
d4ea60 |
name = "tip";
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
case 0x11:
|
|
Packit |
d4ea60 |
name = "tip.pge";
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
case 0x1:
|
|
Packit |
d4ea60 |
name = "tip.pgd";
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
case 0x1d:
|
|
Packit |
d4ea60 |
name = "fup";
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (name) {
|
|
Packit |
d4ea60 |
int ipl = *p >> 5;
|
|
Packit |
d4ea60 |
p++;
|
|
Packit |
d4ea60 |
ip = get_ip_val(&p, end, ipl, &last_ip);
|
|
Packit |
d4ea60 |
fprintf(out_fp, "%s\t%d: %llx", name, ipl, ip);
|
|
Packit |
d4ea60 |
if (get_ip_symbol(ip, buf, sizeof(buf)))
|
|
Packit |
d4ea60 |
fprintf(out_fp, " <%s>\n", buf);
|
|
Packit |
d4ea60 |
else
|
|
Packit |
d4ea60 |
fprintf(out_fp, "\n");
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (*p == 0x99 && LEFT(2)) { /* MODE */
|
|
Packit |
d4ea60 |
if ((p[1] >> 5) == 1) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "mode.tsx");
|
|
Packit |
d4ea60 |
if (p[1] & BIT(0))
|
|
Packit |
d4ea60 |
fprintf(out_fp, " intx");
|
|
Packit |
d4ea60 |
if (p[1] & BIT(1))
|
|
Packit |
d4ea60 |
fprintf(out_fp, " txabort");
|
|
Packit |
d4ea60 |
fprintf(out_fp, "\n");
|
|
Packit |
d4ea60 |
p += 2;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
} else if ((p[1] >> 5) == 0) {
|
|
Packit |
d4ea60 |
fprintf(out_fp, "mode.exec");
|
|
Packit |
d4ea60 |
fprintf(out_fp, " lma=%d", (p[1] & BIT(0)));
|
|
Packit |
d4ea60 |
fprintf(out_fp, " cs.d=%d", !!(p[1] & BIT(1)));
|
|
Packit |
d4ea60 |
fprintf(out_fp, "\n");
|
|
Packit |
d4ea60 |
p += 2;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
if (*p == 0x19 && LEFT(8)) { /* TSC */
|
|
Packit |
d4ea60 |
p++;
|
|
Packit |
d4ea60 |
fprintf(out_fp, "tsc\t%llu\n", get_val(&p, 7));
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (*p == 0b01011001 && LEFT(2)) { /* MTC */
|
|
Packit |
d4ea60 |
fprintf(out_fp, "mtc\t%u\n", p[1]);
|
|
Packit |
d4ea60 |
p += 2;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if ((*p & 3) == 3) { /* CYC */
|
|
Packit |
d4ea60 |
u64 cyc = *p >> 2;
|
|
Packit |
d4ea60 |
unsigned shift = 4;
|
|
Packit |
d4ea60 |
if ((*p & 4) && LEFT(1)) {
|
|
Packit |
d4ea60 |
do {
|
|
Packit |
d4ea60 |
p++;
|
|
Packit |
d4ea60 |
cyc |= (*p >> 1) << shift;
|
|
Packit |
d4ea60 |
shift += 7;
|
|
Packit |
d4ea60 |
} while ((*p & 1) && LEFT(1));
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
fprintf(out_fp, "cyc\t%llu\n", cyc);
|
|
Packit |
d4ea60 |
p++;
|
|
Packit |
d4ea60 |
continue;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
print_unknown(p, end, map);
|
|
Packit |
d4ea60 |
break;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
if (p < end || skipped)
|
|
Packit |
d4ea60 |
fprintf(out_fp, "%lu bytes undecoded\n", (end - p) + skipped);
|
|
Packit |
d4ea60 |
if (overflow)
|
|
Packit |
d4ea60 |
fprintf(out_fp, "%lu overflows\n", overflow);
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
int fastdecode(char *in, char *out)
|
|
Packit |
d4ea60 |
{
|
|
Packit |
d4ea60 |
size_t len;
|
|
Packit |
d4ea60 |
unsigned char *map = mapfile(in, &len;;
|
|
Packit |
d4ea60 |
if (!map) {
|
|
Packit |
d4ea60 |
fprintf(fp, "Cannot map file: %s\n", in);
|
|
Packit |
d4ea60 |
return FALSE;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
if ((out_fp = fopen(out, "w")) == NULL) {
|
|
Packit |
d4ea60 |
fprintf(fp, "Cannot open file: %s\n", out);
|
|
Packit |
d4ea60 |
return FALSE;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
decode_buffer(map, len);
|
|
Packit |
d4ea60 |
unmapfile(map, len);
|
|
Packit |
d4ea60 |
fclose(out_fp);
|
|
Packit |
d4ea60 |
|
|
Packit |
d4ea60 |
return TRUE;
|
|
Packit |
d4ea60 |
}
|
|
Packit |
d4ea60 |
|