Files
s390-tools/libvmdump/vm_dump.cpp
Jan Höppner 428d41034e libvmdump: Fix -Wrestrict warning
Get rid of the following GCC8 compile warning by using different buffers
for input/output:

In file included from vmdump_convert.cpp:13:
vm_dump.h: In member function ‘void VMDump::ebcAsc(char*, size_t)
const’:
vm_dump.h:145:26: warning: passing argument 2 to restrict-qualified
parameter aliases with argument 4 [-Wrestrict]
   iconv(ebcdicAsciiConv, &inout, &len, &inout, &len);
                          ^~~~~~        ~~~~~~
vm_dump.h:145:34: warning: passing argument 3 to restrict-qualified
parameter aliases with argument 5 [-Wrestrict]
   iconv(ebcdicAsciiConv, &inout, &len, &inout, &len);
                                  ^~~~          ~~~~

Signed-off-by: Jan Höppner <hoeppner@linux.ibm.com>
2018-12-11 15:52:07 +01:00

625 lines
16 KiB
C++

/*
* vmdump - z/VM dump conversion library
*
* Register content classes:
* VMDump, VMDumpClassic, VMDump64, VMDump64Big, VMDump32
*
* Copyright IBM Corp. 2004, 2017
*
* s390-tools is free software; you can redistribute it and/or modify
* it under the terms of the MIT license. See LICENSE for details.
*/
#include <ctype.h>
#include <stdint.h>
#include <time.h>
#include "vm_dump.h"
Dump::DumpType VMDump::getDumpType(const char* inputFileName)
{
uint8_t fmbk_id[8] = {0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2};
struct _fir_basic fir;
struct _fmbk fmbk;
struct _adsr adsr;
char msg[200];
FILE* fh;
fh = fopen(inputFileName,"r");
if (!fh) {
sprintf(msg,"Could not open '%s'",inputFileName);
throw DumpErrnoException(msg);
}
/* Record 1: adsr */
dump_read(&adsr, sizeof(adsr), 1, fh);
/* Record 2: fmbk */
dump_seek(fh, 0x1000, SEEK_SET);
if (fread(&fmbk, sizeof(fmbk), 1, fh) != 1) {
if(ferror(fh)) {
sprintf(msg,"Could not read header of vmdump '%s'",
inputFileName);
fclose(fh);
throw DumpErrnoException(msg);
} else{
sprintf(msg,"Input file '%s' is not a vmdump",
inputFileName);
fclose(fh);
throw DumpException(msg);
}
}
/* Check if this is a vmdump */
if (memcmp(fmbk.id, fmbk_id, 8) != 0 ||
adsr.dump_type != 0xe5d4c4e4d4d74040ULL) {
fclose(fh);
sprintf(msg, "Input file '%s' is not a vmdump", inputFileName);
throw DumpException(msg);
}
/* Record 3-7: fir */
dump_seek(fh, (fmbk.rec_nr_fir - 1) * 0x1000, SEEK_SET);
if(fread(&fir, sizeof(fir), 1, fh) != 1) {
if (ferror(fh)) {
sprintf(msg,"Could not read header of vmdump '%s'",
inputFileName);
fclose(fh);
throw DumpErrnoException(msg);
}
else{
sprintf(msg, "Could not read header of vmdump '%s'",
inputFileName);
fclose(fh);
throw DumpException(msg);
}
}
fclose(fh);
if (fir.fir_format == 0) {
return DT_VM32;
} else if (fir.fir_format == 0x02) {/*XXX && (fir.dump_format == 0x1))*/
return DT_VM64_BIG;
} else if (fir.fir_format == 0x82) {
return DT_VM64;
} else {
return DT_UNKNOWN;
}
}
VMDump::VMDump(const char *fileName) : Dump(fileName, "rb")
{
uint8_t fmbk_id[8] = {0xc8, 0xc3, 0xd7, 0xc4, 0xc6, 0xd4, 0xc2, 0xd2};
ebcdicAsciiConv = iconv_open("ISO-8859-1", "EBCDIC-US");
/* Record 1: adsrRecord */
dump_seek(fh,0,SEEK_SET);
dump_read(&adsrRecord,sizeof(adsrRecord),1,fh);
if(debug) {
char buf_asc[1024];
char buf[1024];
int i;
fprintf(stderr, "off=%d\n", adsrRecord.sec5_offset);
dump_seek(fh, adsrRecord.sec5_offset, SEEK_SET);
dump_read(buf, adsrRecord.sec5_len, 1, fh);
ebcAsc(buf, buf_asc, adsrRecord.sec5_len);
for (i=0; i < adsrRecord.sec5_len; i++) {
if ((buf_asc[i]==0) || iscntrl(buf_asc[i]))
buf_asc[i]=' ';
}
buf_asc[adsrRecord.sec5_len] = 0;
printf("symptom string1: %s\n",buf_asc);
}
/* Record 2: fmbk */
dump_seek(fh,0x1000,SEEK_SET);
dump_read(&fmbkRecord,sizeof(fmbkRecord),1,fh);
/* Check if this is a vmdump */
if(memcmp(fmbkRecord.id, fmbk_id, 8) != 0) {
throw DumpException("Input file is not a vmdump");
}
/* Record 3-7: fir records read by subclasses */
/* Record 8: albk */
dump_seek(fh,(fmbkRecord.rec_nr_access-1)*0x1000 ,SEEK_SET);
dump_read(&albkRecord,sizeof(albkRecord),1,fh);
}
struct timeval VMDump::getDumpTime(void) const
{
struct timeval rc;
s390TodToTimeval(adsrRecord.tod,&rc);
return rc;
}
void VMDump::printDebug(void)
{
struct timeval time;
char fmbk_id[8];
char albk_id[8];
s390TodToTimeval(adsrRecord.tod, &time);
/* adsr */
printf("time : %s\n", ctime(&time.tv_sec));
printf("stat1 : %x\n", adsrRecord.record_status_flag1);
printf("stat2 : %x\n", adsrRecord.record_status_flag2);
printf("sec 2 len: %i\n", adsrRecord.sec2_len);
printf("sec 2.1 len: %i/%i\n", adsrRecord.sec2_1_len,
adsrRecord.sec2_1_offset);
printf("sec 3 len: %i/%i\n", adsrRecord.sec3_len,
adsrRecord.sec3_offset);
printf("sec 4 len: %i/%i\n", adsrRecord.sec4_len,
adsrRecord.sec4_offset);
printf("sec 5 len: %i/%i\n", adsrRecord.sec5_len,
adsrRecord.sec5_offset);
printf("sec 6 len: %i/%i\n", adsrRecord.sec6_len,
adsrRecord.sec6_offset);
/* fmbk */
ebcAsc(fmbkRecord.id, fmbk_id, sizeof(fmbkRecord.id));
fmbk_id[7] = 0;
printf("id : %s\n", fmbk_id);
printf("fir rec nr: %i\n", fmbkRecord.rec_nr_fir);
printf("vec rec nr: %i\n", fmbkRecord.rec_nr_vector);
printf("access rec nr: %i\n", fmbkRecord.rec_nr_access);
/* albk */
ebcAsc(albkRecord.id, albk_id, sizeof(albkRecord.id));
albk_id[7]=0;
printf("ALBK id : %s\n",albk_id);
}
void VMDump::printInfo(void)
{
struct timeval time;
s390TodToTimeval(adsrRecord.tod,&time);
fprintf(stderr, " date........: %s",ctime(&time.tv_sec));
}
int VMDump::seekMem(uint64_t offset)
{
if (offset != 0) {
return -1;
}
pageOffset = 0;
return 0;
}
void VMDump::readMem(char* buf, int size)
{
int i;
if (pageOffset == 0)
dump_seek(fh, memoryStartRecord, SEEK_SET);
if (size % 0x1000 != 0) {
throw(DumpException("internal error: VMDump::readMem() " \
"can only handle sizes which are multiples of page size"));
}
for(i = 0; i < size; i += 0x1000) {
if(testPage(pageOffset)) {
dump_read(buf + i, 0x1000, 1, fh);
} else {
memset(buf + i, 0, 0x1000);
}
pageOffset += 1;
}
}
VMDump::~VMDump(void)
{
}
/*****************************************************************************/
/* VMDumpClassic: traditional 32/64 bit vmdump (before z/VM 5.2) */
/*****************************************************************************/
VMDumpClassic::VMDumpClassic(const char *fileName) : VMDump(fileName)
{
int storageKeyPages,bitMapPages;
pageOffset = 0;
/* Record 9: asibk */
dump_seek(fh,fmbkRecord.rec_nr_access * 0x1000,SEEK_SET);
dump_read(&asibkRecord,sizeof(asibkRecord),1,fh);
/* Record 10: bitmaps */
dump_seek(fh,(fmbkRecord.rec_nr_access + 1)* 0x1000 ,SEEK_SET);
bitmap = new char[asibkRecord.storage_size_2GB / (0x1000 * 8)];
dump_read(bitmap,asibkRecord.storage_size_2GB / (0x1000*8),1,fh);
bitMapPages=asibkRecord.storage_size_2GB / (0x1000 * 8);
if (bitMapPages % 0x1000 != 0)
bitMapPages = bitMapPages/0x1000 + 1;
else
bitMapPages = bitMapPages/0x1000;
storageKeyPages=asibkRecord.storage_size_2GB / 0x1000;
if(storageKeyPages % 0x1000 != 0) {
storageKeyPages = storageKeyPages/0x1000 + 1;
} else {
storageKeyPages = storageKeyPages/0x1000;
}
/* Skip storage keys */
memoryStartRecord = (fmbkRecord.rec_nr_access + 1) *0x1000 /* 0x9000 */
+ (bitMapPages + storageKeyPages)*0x1000;
if(debug) {
printf("Mem Offset: %llx\n", (long long) memoryStartRecord);
}
}
void VMDumpClassic::printInfo(void)
{
VMDump::printInfo();
fprintf(stderr, " storage.....: %i MB\n",
asibkRecord.storage_size_2GB/(1024*1024));
}
VMDumpClassic::~VMDumpClassic(void)
{
delete bitmap;
}
/*****************************************************************************/
/* VMDump32: 32 bit vmdump */
/*****************************************************************************/
VMDump32::VMDump32(const char* filename) : VMDumpClassic(filename)
{
int i;
if(!fh) {
return;
}
dump_seek(fh,(fmbkRecord.rec_nr_fir-1)* 0x1000 ,SEEK_SET);
dump_read(&fir32Record,sizeof(fir32Record),1,fh);
fir32OtherRecords = new _fir_other_32[fir32Record.online_cpus];
for(i=0; i < fir32Record.online_cpus; i++) {
/* fir other */
dump_read(&fir32OtherRecords[i],sizeof(fir32OtherRecords[i]),1,
fh);
}
if(debug)
printDebug();
}
RegisterContent32 VMDump32::getRegisterContent(void)
{
RegisterContent32 rc;
RegisterSet32 rs;
int cpu;
/* First CPU */
memcpy(&rs.gprs, &fir32Record.gprs, sizeof(rs.gprs));
memcpy(&rs.crs, &fir32Record.crs, sizeof(rs.crs));
memcpy(&rs.acrs, &fir32Record.acrs, sizeof(rs.acrs));
memcpy(&rs.psw, &fir32Record.psw, sizeof(rs.psw));
memcpy(&rs.prefix, &fir32Record.prefix, sizeof(rs.prefix));
memcpy(&rs.fprs, &fir32Record.fprs, sizeof(rs.fprs));
memcpy(&rs.cpuTimer, &fir32Record.cpu_timer, sizeof(rs.cpuTimer));
memcpy(&rs.clkCmp, &fir32Record.clock_cmp, sizeof(rs.clkCmp));
rc.addRegisterSet(rs);
/* Other online cpus */
for(cpu = 0; cpu < fir32Record.online_cpus; cpu++) {
memcpy(&rs.gprs, &fir32OtherRecords[cpu].gprs, sizeof(rs.gprs));
memcpy(&rs.crs, &fir32OtherRecords[cpu].crs, sizeof(rs.crs));
memcpy(&rs.acrs, &fir32OtherRecords[cpu].acrs, sizeof(rs.acrs));
/* No psw for ESA vmdumps */
rs.psw[0] = 0xdeadbeef;
rs.psw[1] = 0xdeadbeef;
memcpy(&rs.prefix, &fir32OtherRecords[cpu].prefix,
sizeof(rs.prefix));
memcpy(&rs.fprs, &fir32OtherRecords[cpu].fprs, sizeof(rs.fprs));
memcpy(&rs.cpuTimer, &fir32OtherRecords[cpu].cpu_timer,
sizeof(rs.cpuTimer));
memcpy(&rs.clkCmp, &fir32OtherRecords[cpu].clock_cmp,
sizeof(rs.clkCmp));
rc.addRegisterSet(rs);
}
return rc;
}
void VMDump32::printDebug(void)
{
int i;
VMDump::printDebug();
printf("prefix: %x\n", fir32Record.prefix);
printf("cpus: %x\n", fir32Record.online_cpus);
printf("psw: %08x %08x\n", fir32Record.psw[0], fir32Record.psw[1]);
for (i=0; i < fir32Record.online_cpus; i++) {
/* fir other */
printf("prefix (%i): %x\n", i, fir32OtherRecords[i].prefix);
}
}
void
VMDump32::printInfo(void)
{
fprintf(stderr, "vmdump information:\n");
fprintf(stderr, " architecture: 32 bit\n");
VMDumpClassic::printInfo();
fprintf(stderr, " cpus........: %x\n", fir32Record.online_cpus + 1);
}
VMDump32::~VMDump32(void)
{
delete fir32OtherRecords;
}
/*****************************************************************************/
/* VMDump64: 64 bit vmdump for old vmdump format (z/VM < 5.2) */
/*****************************************************************************/
VMDump64::VMDump64(const char* filename) : VMDumpClassic(filename)
{
int i;
if(!fh) {
return;
}
dump_seek(fh,(fmbkRecord.rec_nr_fir-1)* 0x1000 ,SEEK_SET);
dump_read(&fir64Record,sizeof(fir64Record),1,fh);
fir64OtherRecords = new _fir_other_64[fir64Record.online_cpus];
for (i=0; i < fir64Record.online_cpus; i++) {
/* fir other */
dump_read(&fir64OtherRecords[i], sizeof(fir64OtherRecords[i]),
1, fh);
}
if(debug)
printDebug();
}
void VMDump64::printDebug(void)
{
int i;
VMDump::printDebug();
printf("prefix: %x\n", fir64Record.prefix);
printf("cpus: %x\n", fir64Record.online_cpus);
printf("psw: %016llx %016llx\n", (long long)fir64Record.psw[0],
(long long)fir64Record.psw[1]);
for (i=0; i < fir64Record.online_cpus; i++) {
/* fir other */
printf("prefix (%i): %x\n", i, fir64OtherRecords[i].prefix);
}
}
void VMDump64::printInfo(void)
{
fprintf(stderr, "vmdump information:\n");
fprintf(stderr, " architecture: 64 bit\n");
VMDumpClassic::printInfo();
fprintf(stderr, " cpus........: %x\n",fir64Record.online_cpus + 1);
}
RegisterContent64 VMDump64::getRegisterContent(void)
{
RegisterContent64 rc;
RegisterSet64 rs;
int cpu;
/* First CPU */
memcpy(&rs.gprs, &fir64Record.gprs, sizeof(rs.gprs));
memcpy(&rs.crs, &fir64Record.crs, sizeof(rs.crs));
memcpy(&rs.acrs, &fir64Record.acrs, sizeof(rs.acrs));
memcpy(&rs.psw, &fir64Record.psw, sizeof(rs.psw));
memcpy(&rs.prefix, &fir64Record.prefix, sizeof(rs.prefix));
memcpy(&rs.fprs, &fir64Record.fprs, sizeof(rs.fprs));
memcpy(&rs.cpuTimer, &fir64Record.cpu_timer, sizeof(rs.cpuTimer));
memcpy(&rs.clkCmp, &fir64Record.clock_cmp, sizeof(rs.clkCmp));
memcpy(&rs.fpCr, &fir64Record.fp_cntrl_reg, sizeof(rs.fpCr));
rc.addRegisterSet(rs);
/* other online cpus */
for (cpu = 0; cpu < fir64Record.online_cpus; cpu++) {
memcpy(&rs.gprs, &fir64OtherRecords[cpu].gprs, sizeof(rs.gprs));
memcpy(&rs.crs, &fir64OtherRecords[cpu].crs, sizeof(rs.crs));
memcpy(&rs.acrs, &fir64OtherRecords[cpu].acrs, sizeof(rs.acrs));
memcpy(&rs.psw, &fir64OtherRecords[cpu].psw, sizeof(rs.psw));
memcpy(&rs.prefix, &fir64OtherRecords[cpu].prefix,
sizeof(rs.prefix));
memcpy(&rs.fprs, &fir64OtherRecords[cpu].fprs, sizeof(rs.fprs));
memcpy(&rs.cpuTimer, &fir64OtherRecords[cpu].cpu_timer,
sizeof(rs.cpuTimer));
memcpy(&rs.clkCmp, &fir64OtherRecords[cpu].clock_cmp,
sizeof(rs.clkCmp));
memcpy(&rs.fpCr, &fir64OtherRecords[cpu].fp_cntrl_reg,
sizeof(rs.fpCr));
rc.addRegisterSet(rs);
}
return rc;
}
VMDump64::~VMDump64(void)
{
delete fir64OtherRecords;
}
/*****************************************************************************/
/* VMDump64Big: 64 bit vmdump with new big storage dump format */
/*****************************************************************************/
VMDump64Big::VMDump64Big(const char* filename) : VMDump(filename)
{
uint64_t pageNum, nrDumpedPages;
int i, j;
if(!fh) {
return;
}
/* Record 9: asibk */
dump_seek(fh, fmbkRecord.rec_nr_access * 0x1000,SEEK_SET);
dump_read(&asibkRecordNew, sizeof(asibkRecordNew), 1, fh);
/* Record 10: bitmaps: */
/* Read all bitmap pages and setup bitmap array */
pageNum = 0;
nrDumpedPages = asibkRecordNew.storage_size_def_store / 0x1000;
memoryStartRecord = (fmbkRecord.rec_nr_access + 1) * 0x1000;
bitmap = new char[asibkRecordNew.storage_size_def_store/(0x1000 * 8)];
if(!bitmap) {
throw(DumpErrnoException("out of memory"));
}
memset(bitmap,0,asibkRecordNew.storage_size_def_store/(0x1000 * 8));
dump_seek(fh,(fmbkRecord.rec_nr_access + 1)* 0x1000 ,SEEK_SET);
do {
char bmIndexPage[0x1000];
dump_read(bmIndexPage, sizeof(bmIndexPage), 1, fh);
memoryStartRecord += 0x1000;
for (i=0; i < 0x1000; i++) {
if(testBitmapPage(bmIndexPage, i)) {
char bmPage[0x1000];
dump_read(bmPage,sizeof(bmPage),1,fh);
memoryStartRecord += 0x1000;
for(j = 0; j < 0x1000; j++) {
if(testBitmapKeyPage(bmPage, j)) {
setPageBit(pageNum);
}
pageNum++;
if(pageNum == nrDumpedPages) {
goto all_bitmaps_read;
}
}
} else {
pageNum += 0x1000; /* Empty pages */
}
}
} while (pageNum < nrDumpedPages);
all_bitmaps_read:
if(debug)
printf("Mem Offset: %llx\n", (long long)memoryStartRecord);
dump_seek(fh, (fmbkRecord.rec_nr_fir-1)* 0x1000, SEEK_SET);
dump_read(&fir64Record, sizeof(fir64Record), 1, fh);
fir64OtherRecords = new _fir_other_64[fir64Record.online_cpus];
for (i=0; i < fir64Record.online_cpus; i++) {
/* fir other */
dump_read(&fir64OtherRecords[i], sizeof(fir64OtherRecords[i]),
1, fh);
}
if(debug)
printDebug();
}
void VMDump64Big::printDebug(void)
{
int i;
VMDump::printDebug();
printf("prefix: %x\n", fir64Record.prefix);
printf("cpus: %x\n", fir64Record.online_cpus);
printf("psw: %016llx %016llx\n", (long long)fir64Record.psw[0],
(long long)fir64Record.psw[1]);
for (i=0; i < fir64Record.online_cpus; i++) {
/* fir other */
printf("prefix (%i): %x\n", i, fir64OtherRecords[i].prefix);
}
}
void VMDump64Big::printInfo(void)
{
fprintf(stderr, "vmdump information:\n");
fprintf(stderr, " architecture: 64 bit (big)\n");
fprintf(stderr, " storage.....: %lli MB\n",
(long long)asibkRecordNew.storage_size_def_store / (1024*1024));
VMDump::printInfo();
fprintf(stderr, " cpus........: %x\n", fir64Record.online_cpus + 1);
}
RegisterContent64 VMDump64Big::getRegisterContent(void)
{
RegisterContent64 rc;
RegisterSet64 rs;
int cpu;
/* First CPU */
memcpy(&rs.gprs, &fir64Record.gprs, sizeof(rs.gprs));
memcpy(&rs.crs, &fir64Record.crs, sizeof(rs.crs));
memcpy(&rs.acrs, &fir64Record.acrs, sizeof(rs.acrs));
memcpy(&rs.psw, &fir64Record.psw, sizeof(rs.psw));
memcpy(&rs.prefix, &fir64Record.prefix, sizeof(rs.prefix));
memcpy(&rs.fprs, &fir64Record.fprs, sizeof(rs.fprs));
memcpy(&rs.cpuTimer, &fir64Record.cpu_timer, sizeof(rs.cpuTimer));
memcpy(&rs.clkCmp, &fir64Record.clock_cmp, sizeof(rs.clkCmp));
memcpy(&rs.fpCr, &fir64Record.fp_cntrl_reg, sizeof(rs.fpCr));
rc.addRegisterSet(rs);
/* other online cpus */
for(cpu = 0; cpu < fir64Record.online_cpus; cpu++) {
memcpy(&rs.gprs, &fir64OtherRecords[cpu].gprs, sizeof(rs.gprs));
memcpy(&rs.crs, &fir64OtherRecords[cpu].crs, sizeof(rs.crs));
memcpy(&rs.acrs, &fir64OtherRecords[cpu].acrs, sizeof(rs.acrs));
memcpy(&rs.psw, &fir64OtherRecords[cpu].psw, sizeof(rs.psw));
memcpy(&rs.prefix, &fir64OtherRecords[cpu].prefix,
sizeof(rs.prefix));
memcpy(&rs.fprs, &fir64OtherRecords[cpu].fprs, sizeof(rs.fprs));
memcpy(&rs.cpuTimer, &fir64OtherRecords[cpu].cpu_timer,
sizeof(rs.cpuTimer));
memcpy(&rs.clkCmp, &fir64OtherRecords[cpu].clock_cmp,
sizeof(rs.clkCmp));
memcpy(&rs.fpCr, &fir64OtherRecords[cpu].fp_cntrl_reg,
sizeof(rs.fpCr));
rc.addRegisterSet(rs);
}
return rc;
}
VMDump64Big::~VMDump64Big(void)
{
delete bitmap;
delete fir64OtherRecords;
}