?? dumprom.cpp
字號:
/* (C) 2003-2007 Willem Jan Hengeveld <itsme@xs4all.nl>
* Web: http://www.xs4all.nl/~itsme/
* http://wiki.xda-developers.com/
*
* $Id: dumprom.cpp 1502 2007-04-15 07:54:20Z itsme $
*/
// for more info on rom layout, see
// http://www.xs4all.nl/~itsme/projects/xda/wince-rom-layout.html
// compile with: cl /Wall /wd4710 /wd4217 /wd4668 /wd4820 /EHsc dumprom.cpp nkcompr.lib
// nkcompr.lib is in "/WINCE410/PUBLIC/COMMON/OAK/LIB/X86/RETAIL/nkcompr.lib"
// compiler used is "Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.00.9466 for 80x86"
// ( from visual studio .net )
// some details for my specific rom
// 80000000-80028000 is copied to ram: 8c078000-8c0a0000 - this is the bootloader.
//
// (0x80001000, 0x27000, "boootloader");
// I don't know how to find this other than that is is not referenced anywhere.
// (0x81400000, 0x1284, "rsa sig for all XIP sections");
// - the header file mentions a ROM_CHAIN_OFFSET, but I don't know how to
// interpret that.
// - the xip regions are not very accurate, most are too short.
// -> the 'end's are only displayed when '-v' is specified.
//
// (0x81900000, 0, "");
// (0x81940000, 0, "");
// (0x81f00000, 0, "saved contacts etc.");
// (0x82000000, 0, "end");
//
// example commandline:
// dumprom rom80000000.bin -x 0x81400000 -u "0x81f00000:0:saved contacts" -u "0x80001000:0x27000:bootloader" -u "0x81900000:0:" -u "0x81940000:0:" -d tst > info.txt
//
// some images start at 80040000, in that case you should dump it like this:
// dumprom 3-15-15-ENG-O2euro.nb1 0x80040000
//
// or another one I have has a 1024 byte header, and no bootloader, dump it with:
//
// dumprom ce.img 0x8003fc00
//
// or another one I saw, has a 1024 byte header and a bootloader, dump it with:
//
// dumprom ce_boot.img 0x7ffffc00
//
//
// how to find the file offset:
//
// I may have to automate this. what I do to find this offset, is
// look at where I see "ECEC" -> offset 0x5b
//
// if "ECEC" is followed by 0x8c0a0000 then this 'ECEC'
// must be the bootloader's, in which case it should be at
// rom-offset 0x80000040 -> use filestart-offset
// of 0x80000040-0x5b= 0x7fffffe5
//
// but in this case, ECEC is followed by an address that is in
// the address range of the rom (0x80000000-0x82000000).
//
// in that case this 'ECEC' must be at 0x80040040 -> use filestart ofs
// of 0x80040040-0x5b= 0x8003ffe5
//
// testing with spv phone rom:
// - spv phone rom starts at 81c00000
//
// bug:
// determine start offset only finds majority, this is not good.
// each block can have it's own start offset
//
// because of this, only one block is loaded into m_blocks,
// causing calls to DumpExtensions to fail with 'GetPtr cannot find offset'
//
// wm2005 xip files have the corrected offset incorrect i think.
// --> allow to prevent correctiong offset.
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
#include <string>
using namespace std;
char *g_outputdirectory=NULL;
int g_verbose=0;
bool b_use_negative_rva= true;
bool b_wm2005_rom= false;
#ifndef _WIN32
typedef bool BOOL;
typedef char CHAR;
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned long DWORD;
typedef long LONG;
typedef unsigned long ULONG;
typedef unsigned short USHORT;
typedef char *LPSTR;
typedef void *LPVOID;
typedef void *PVOID;
typedef BYTE *LPBYTE;
typedef struct _tagFILETIME {
DWORD dwLowDateTime;
DWORD dwHighDateTime;
} FILETIME;
#define _vsnprintf vsnprintf
#define _snprintf snprintf
#define __int64 long long
#define strnicmp strncasecmp
#else
#include <windows.h>
#endif
class MemoryBlock {
public:
BYTE *data;
DWORD length;
DWORD start;
DWORD end;
/* no destructor, to make memory management without copy constructors and refcounting easy */
/* I currently don't care about the data buffer leaking */
bool InRange(DWORD offset) { return (start <= offset && offset < end); }
bool operator <(const MemoryBlock& mb) const { return start < mb.start; }
bool operator <(DWORD offset) const { return end < offset; }
};
typedef vector<MemoryBlock> MemoryBlockVector;
class MemoryMapIterator {
public:
MemoryMapIterator(const MemoryBlockVector::iterator& start, const MemoryBlockVector::iterator& end)
: m_end(end)
{
m_block= start;
if (m_block != m_end)
m_ofs= (*m_block).start;
else
m_ofs= 0;
}
MemoryMapIterator(const MemoryMapIterator& m)
: m_end(m.m_end), m_ofs(m.m_ofs), m_block(m.m_block)
{
}
void findnext()
{
while (m_block!=m_end && m_ofs>=(*m_block).end) {
++m_block;
}
if (m_block==m_end) {
m_ofs= 0;
}
else if (m_ofs<(*m_block).start) {
m_ofs= (*m_block).start;
}
}
MemoryMapIterator& operator++() // prefix inc
{
return *this += 1;
}
MemoryMapIterator& operator+=(int stepsize)
{
m_ofs+=stepsize;
findnext();
return *this;
}
bool operator==(const MemoryMapIterator& a) const
{
return m_block==a.m_block && m_ofs==a.m_ofs;
}
bool operator!=(const MemoryMapIterator& a) const
{
return !(*this==a);
}
void *GetPtr() const
{
if (m_block!=m_end)
return (*m_block).data+(m_ofs-(*m_block).start);
else
return NULL;
}
BYTE GetByte() const
{
BYTE *p= (BYTE*)GetPtr();
if (p==NULL)
return 0;
return *p;
}
DWORD GetWord() const
{
WORD *p= (WORD*)GetPtr();
if (p==NULL)
return 0;
return *p;
}
DWORD GetDword() const
{
BYTE *p= (BYTE*)GetPtr();
if (p==NULL)
return 0;
return *p;
}
public:
MemoryBlockVector::iterator m_block;
DWORD m_ofs;
const MemoryBlockVector::iterator& m_end;
};
class MemoryMap {
public:
bool LoadFile(DWORD offset, char *filename, DWORD fileoffset, DWORD length);
void *GetPtr(DWORD offset);
DWORD GetOfs(void *ptr);
BYTE GetByte(DWORD offset);
DWORD GetDword(DWORD offset);
DWORD FirstAddress();
DWORD LastAddress();
MemoryMapIterator begin();
const MemoryMapIterator end();
private:
MemoryBlockVector m_blocks;
};
MemoryMap g_mem;
class MemRegion {
public:
DWORD start;
DWORD end;
DWORD length;
string *description;
/* no destructor, to make memory management without copy constructors and refcounting easy */
/* I currently don't care about the description buffer leaking */
MemRegion(DWORD start, DWORD end) : start(start), end(end), description(NULL), length(end-start) {}
bool operator <(const MemRegion& r) const { return start < r.start || (start==r.start && length<r.length); }
// bug: this can result in very long invalid memory access
// .... todo: should skip invalid regions
DWORD FirstNonzero() {
for (DWORD i=start ; i<end ; ++i)
if (g_mem.GetByte(i))
return i;
return end;
}
DWORD LastNonzero() {
for (DWORD i=end-1 ; i>=start ; --i)
if (g_mem.GetByte(i))
return i;
return start-1;
}
};
typedef vector<MemRegion> MemRegionVector;
class MemRegions {
public:
MemRegion& MarkRange(DWORD start, DWORD end, const char *msg, ...);
MemRegion& MarkRegion(DWORD start, DWORD length, const char *msg, ...);
MemRegion& MarkRegion_v(DWORD start, DWORD length, const char *msg, va_list ap);
void DumpMemoryMap();
private:
MemRegionVector m_list;
};
//--------------------------- global variables
MemRegions g_regions;
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
bool MemoryMap::LoadFile(DWORD offset, char *filename, DWORD fileoffset, DWORD length)
{
FILE *f= fopen(filename, "rb");
if (f==NULL)
{
perror(filename);
return false;
}
if (length==0)
{
if (fseek(f, 0, SEEK_END))
{
perror(filename);
fclose(f);
return false;
}
length= ftell(f)-fileoffset;
}
if (length==0)
{
fclose(f);
printf("length not known\n");
return false;
}
MemoryBlock mb;
mb.data= new BYTE[length];
if (mb.data==NULL)
{
fclose(f);
printf("error allocating memory\n");
return false;
}
mb.length= length;
mb.start= offset;
mb.end= offset+length;
if (fseek(f, fileoffset, SEEK_SET))
{
perror(filename);
fclose(f);
return false;
}
size_t nRead= fread(mb.data, 1, mb.length, f);
if (nRead!=mb.length)
{
perror("fread");
fclose(f);
return false;
}
fclose(f);
// keep m_blocks sorted.
MemoryBlockVector::iterator i;
for (i=m_blocks.begin() ; i!=m_blocks.end(); ++i)
if (mb.start < (*i).start)
break;
m_blocks.insert(i, mb);
if (g_verbose)
printf("block %ld added buf=%08lx %08lx\n", m_blocks.size(), (DWORD)mb.data, mb.length);
return true;
}
BYTE MemoryMap::GetByte(DWORD offset)
{
BYTE *p= (BYTE*)GetPtr(offset);
if (p==NULL)
return 0;
return *p;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -