#include "util/ReadWriter.h" #include "util/rw/FileReader.h" #include "vectorutils.h" #include "stringutils.h" #include "debug.h" #include // struct defs are in: // ~/sources/wm500aku/PUBLIC/COMMON/OAK/INC/dwcedump.h // ~/sources/wince500/PRIVATE/WINCEOS/COREOS/NK/KERNEL/kdriver.c [ kernel side ] // ~/sources/wince500/PRIVATE/WINCEOS/COREOS/NK/OSAXS/dwdmpgen.cpp // // http://forum.xda-developers.com/showthread.php?t=419635 // http://msdn.microsoft.com/en-us/library/ms939593.aspx // http://msdn.microsoft.com/en-us/library/ms939646.aspx _MINIDUMP_HEADER // // the kdmp data is created by the kernel, and accessed through IOCTL_KLIB_READWATSON // typedef std::vector DwordList; typedef std::vector ByteVectorList; class kdmp_stream { uint16_t _hdrsize; uint16_t _recsize; uint32_t _nprops; protected: ReadWriter_ptr _r; uint32_t _ofs; uint32_t _size; public: kdmp_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : _hdrsize(0), _recsize(0), _nprops(0), _r(r), _ofs(ofs), _size(size) { _r->setpos(_ofs); } void readhdr() { _hdrsize= _r->read16le(); _recsize= _r->read16le(); _nprops= _r->read32le(); } std::string readstring(uint32_t ofs) { _r->setpos(ofs); uint32_t bytelen= _r->read32le(); std::Wstring data; data.resize(bytelen/2); _r->read((uint8_t*)&data[0], bytelen); // todo: this strips everything after the NUL // -> need to fix return ToString(data); } StringList readstringlist(uint32_t ofs) { std::string strl= readstring(ofs); StringList l; size_t ix= 0; while (ix!=strl.npos && ixsetpos(ofs); while (n--) l.push_back(_r->read32le()); return l; } struct fieldinfo { uint32_t id; uint32_t size; uint32_t p_name; uint32_t p_fmt; std::string name; std::string format; fieldinfo() : id(0), size(0), p_name(0), p_fmt(0) { } }; typedef boost::shared_ptr fieldinfo_ptr; typedef std::vector fieldinfo_list; typedef std::vector kdmp_elements; typedef boost::shared_ptr kdmp_elements_ptr; kdmp_elements_ptr read_element_list(uint32_t ofs) { _r->setpos(ofs); // _CEDUMP_ELEMENT_LIST uint16_t hsize= _r->read16le(); uint16_t fisize= _r->read16le(); uint32_t nfields= _r->read32le(); uint32_t nelems= _r->read32le(); uint32_t p_elems= _r->read32le(); ofs += 16; if (fisize!=16) { printf("unknown fieldinfo size: %02x\n", fisize); } fieldinfo_list finfo; for (unsigned f_ix= 0 ; f_ixsize); _r->read(&f[f_ix][0], f[f_ix].size()); } ems->push_back(f); } return ems; } void dump_elist(kdmp_elements_ptr e) { // todo } fieldinfo_ptr read_fieldinfo(uint32_t ofs) { _r->setpos(ofs); // _CEDUMP_FIELD_INFO fieldinfo_ptr f(new fieldinfo()); f->id= _r->read32le(); f->size= _r->read32le(); f->p_name= _r->read32le(); f->p_fmt= _r->read32le(); f->name= readstring(f->p_name); f->format= readstring(f->p_fmt); return f; } }; typedef boost::shared_ptr kdmp_stream_ptr; typedef std::vector streamlist_t; class sysinfo_stream : public kdmp_stream { public: sysinfo_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { // read _CEDUMP_SYSTEM_INFO uint16_t hdrsize= _r->read16le(); uint16_t cpuarch= _r->read16le(); uint32_t cpucount= _r->read32le(); uint32_t proctype= _r->read32le(); uint16_t cpulevel= _r->read16le(); uint16_t cpurevision= _r->read16le(); uint32_t cpufamily= _r->read32le(); uint32_t wincemajor= _r->read32le(); uint32_t winceminor= _r->read32le(); uint32_t wincebuild= _r->read32le(); uint32_t platformid= _r->read32le(); uint32_t lcid= _r->read32le(); uint32_t p_oemstring= _r->read32le(); uint32_t supportflags= _r->read32le(); uint32_t imgfile_machinetype= _r->read32le(); uint32_t p_platformlist= _r->read32le(); uint32_t nrplatforms= _r->read32le(); uint32_t p_platformversion= _r->read32le(); uint32_t instructionset= _r->read32le(); uint32_t kdataptr= _r->read32le(); std::string oemname= readstring(p_oemstring); StringList platforms= readstringlist(p_platformlist); DwordList platversion= readdwords(p_platformversion, 4); printf("h:%04x, cpu:{arch:%04x,n:%d,type:%d,level:%d,rev:%d,fam:%d}, wince:{v%d.%d.%d}\n", hdrsize, cpuarch, cpucount, proctype, cpulevel, cpurevision, cpufamily, wincemajor, winceminor, wincebuild); printf("platform:%d, lcid=%04x, flags=%08x, imgmach:%d, insnset:%d, kdata=%08x\n", platformid, lcid, supportflags, imgfile_machinetype, instructionset, kdataptr); printf(" oem: %s, platforms:[%s], platver: %s\n", oemname.c_str(), JoinStringList(platforms, ",").c_str(), vhexdump(platversion).c_str()); } }; class exception_stream : public kdmp_stream { public: exception_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { // read _CEDUMP_EXCEPTION_STREAM uint16_t hdrsize= _r->read16le(); uint16_t excsize= _r->read16le(); uint16_t ctxsize= _r->read16le(); uint16_t flags= _r->read16le(); uint32_t ownerpid= _r->read32le(); uint32_t curthread= _r->read32le(); uint32_t curprocess= _r->read32le(); uint32_t api_ownerproc= _r->read32le(); uint32_t api_curthread= _r->read32le(); uint32_t api_curprocess= _r->read32le(); // read _CEDUMP_EXCEPTION uint32_t ExceptionCode= _r->read32le(); uint32_t ExceptionFlags= _r->read32le(); uint32_t ExceptionRecord= _r->read32le(); uint32_t ExceptionAddress= _r->read32le(); uint32_t NumberParameters= _r->read32le(); DwordVector ExceptionInformation = readdwords(_ofs+0x34, 15); kdmp_elements_ptr elems= read_element_list(_ofs+0x70); printf("owner=%08x, thread=%08x, proc=%08x, api:%08x/%08x/%08x\n", ownerpid,curthread,curprocess,api_ownerproc,api_curthread,api_curprocess); printf("exc: code=%08x, fl=%08x, rec=%08x, addr=%08x, args:%d : %s\n", ExceptionCode, ExceptionFlags, ExceptionRecord, ExceptionAddress, NumberParameters, vhexdump(ExceptionInformation).c_str()); dump_elist(elems); } }; class modlist_stream : public kdmp_stream { public: modlist_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { kdmp_elements_ptr mods= read_element_list(_ofs); dump_elist(mods); } }; class proclist_stream : public kdmp_stream { public: proclist_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { kdmp_elements_ptr procs= read_element_list(_ofs); dump_elist(procs); } }; class threadlist_stream : public kdmp_stream { public: threadlist_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { kdmp_elements_ptr threads= read_element_list(_ofs); dump_elist(threads); } }; class threadctx_stream : public kdmp_stream { public: threadctx_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { kdmp_elements_ptr threadctxs= read_element_list(_ofs); dump_elist(threadctxs); } }; class callstack_stream : public kdmp_stream { public: callstack_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { // _CEDUMP_THREAD_CALL_STACK_LIST // hdrsize, recsize, count // // _CEDUMP_THREAD_CALL_STACK // {hproc, hthread, rsize, n, rptr} // // _CEDUMP_THREAD_CALL_STACK_FRAME // rptr -> {PC, SP, hproc, ?, ?, pthread, cpsr, ? } } }; class bucketparams_stream : public kdmp_stream { public: bucketparams_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { // _CEDUMP_BUCKET_PARAMETERS // hdrsize, recsize // . } }; class memvirt_stream : public kdmp_stream { public: memvirt_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { // _CEDUMP_MEMORY_LIST uint16_t hdrsize= _r->read16le(); uint16_t entsize= _r->read16le(); uint32_t count= _r->read32le(); struct meminfo { uint64_t start; uint32_t size; uint32_t rva; }; typedef std::vector meminfolist; meminfolist l(count); for (meminfolist::iterator i= l.begin() ; i!=l.end() ; i++) { // MINIDUMP_MEMORY_DESCRIPTOR i->start= _r->read64le(); // MINIDUMP_LOCATION_DESCRIPTOR i->size= _r->read32le(); i->rva= _r->read32le(); } for (meminfolist::iterator i= l.begin() ; i!=l.end() ; i++) { _r->setpos(i->rva); ByteVector data(i->size); _r->read(&data[0], data.size()); bighexdump(i->start, data, hexdumpflags(DUMPUNIT_DWORD, 4, DUMP_HEX_ASCII)|HEXDUMP_WITH_OFFSET|HEXDUMP_SUMMARIZE); } } }; class memphys_stream : public kdmp_stream { public: memphys_stream(ReadWriter_ptr r, uint32_t ofs, uint32_t size) : kdmp_stream(r, ofs, size) { read(); } void read() { // _CEDUMP_MEMORY_LIST } }; static kdmp_stream_ptr make_stream(ReadWriter_ptr r, uint32_t type, uint32_t ofs, uint32_t size) { switch(type) { case 0x8001: return kdmp_stream_ptr(new sysinfo_stream(r, ofs, size)); case 0x8002: return kdmp_stream_ptr(new exception_stream(r, ofs, size)); case 0x8003: return kdmp_stream_ptr(new modlist_stream(r, ofs, size)); case 0x8004: return kdmp_stream_ptr(new proclist_stream(r, ofs, size)); case 0x8005: return kdmp_stream_ptr(new threadlist_stream(r, ofs, size)); case 0x8006: return kdmp_stream_ptr(new threadctx_stream(r, ofs, size)); case 0x8007: return kdmp_stream_ptr(new callstack_stream(r, ofs, size)); case 0x8008: return kdmp_stream_ptr(new memvirt_stream(r, ofs, size)); case 0x8009: return kdmp_stream_ptr(new memvirt_stream(r, ofs, size)); case 0x800a: return kdmp_stream_ptr(new bucketparams_stream(r, ofs, size)); default: return kdmp_stream_ptr(); } } class kdmp_file { ReadWriter_ptr _r; streamlist_t _streams; public: kdmp_file(ReadWriter_ptr r) : _r(r) { read(); } void read() { // read _MINIDUMP_HEADER uint32_t magic= _r->read32le(); if (magic!=0x53444543) printf("magic = %08x\n", magic); uint32_t version= _r->read32le(); if (version!=2) printf("version = %08x\n", version); uint32_t nstreams= _r->read32le(); uint32_t streamdirofs= _r->read32le(); uint32_t checksum= _r->read32le(); uint32_t timestamp= _r->read32le(); uint32_t flags= _r->read32le(); uint32_t unk1= _r->read32le(); printf("chk:%08x, ts:%08x, fl:%08x, u1:%08x\n", checksum, timestamp, flags, unk1); if (streamdirofs>0x20) { ByteVector unk2(streamdirofs-0x20); _r->read(&unk2[0], unk2.size()); if (std::find_if(unk2.begin(), unk2.end(), [](uint8_t t) { return t!=0; })!=unk2.end()) printf("unk2: %s\n", vhexdump(unk2).c_str()); } for (unsigned i= 0 ; isetpos(streamdirofs+12*i); uint32_t type= _r->read32le(); uint32_t ssize= _r->read32le(); uint32_t sofs= _r->read32le(); _streams.push_back(make_stream(_r, type, sofs, ssize)); } } }; int main(int argc, char**argv) { DebugStdOut(); ReadWriter_ptr f(new FileReader(argv[1], FileReader::readonly)); kdmp_file kdmp(f); return 0; }