📄 module.cpp
字号:
desc:
resolve a function address from a hint string
*****************************************************************************/
DWORD Module::resolve_imp_hint_str(const ModuleList &module_list, DWORD hint, const string &str) const{
// no rva nothing to resolve
if(!m_e32.e32_unit[EXP].rva)
return 0;
ExpHdr *expptr = (ExpHdr *)rva2ptr(m_e32.e32_unit[EXP].rva);
DWORD *eatptr = (DWORD *)rva2ptr(expptr->exp_eat);
WORD *ordptr = (WORD *)rva2ptr(expptr->exp_ordinal);
char **nameptr = (char **)rva2ptr(expptr->exp_name);
DWORD ret = 0;
if(hint >= expptr->exp_namecnt || str != (char *)rva2ptr((DWORD)nameptr[hint]))
ret = resolve_imp_str(module_list, str);
else
ret = addr_from_eat(module_list, eatptr[ordptr[hint]]);
if(!ret)
cerr << "Error: Can't find import " << str << " hint " << hint << " in " << m_name << endl;
return ret;
}
/*****************************************************************************
truncate_o32()
in:
none
out:
boolean value indicating success
desc:
truncate a module's o32 data section
*****************************************************************************/
DWORD Module::truncate_o32(O32 &o32){
DWORD length = o32.min_size();
// truncate the data
BYTE *ptr = (BYTE *)rva2ptr(o32.o32_rva) + length;
while(length && !*--ptr)
length--;
o32.o32_psize = length;
return o32.o32_psize;
}
/*****************************************************************************
compress_o32()
in:
none
out:
boolean value indicating success
desc:
compress a module's o32 data section
*****************************************************************************/
DWORD Module::compress_o32(O32 &o32){
if(o32.is_writable())
truncate_o32(o32);
if(!o32.min_size())
return 0; // skip furthur processing since there is nothing to compress
// compress the section
Data compressed_data;
DWORD compressed_size;
compressed_size = m_compressor->cecompress((BYTE *)rva2ptr(o32.o32_rva),
o32.min_size(),
compressed_data.user_fill(o32.min_size()),
o32.min_size() - 1,
1,
page_size());
if(compressed_size == -1) // failure, just make sure it's marked as aligned
o32.o32_flags |= IMAGE_SCN_ALIGN_4BYTES; // flag is ignored in rest of romimage
else if(!compressed_size) // compressed to all zeros
o32.o32_psize = 0;
else{ // compression worked
o32.data.set(compressed_data.ptr(), compressed_size); // chose not to use = operator to allow for explicit resize
o32.o32_flags |= IMAGE_SCN_COMPRESSED;
o32.o32_psize = compressed_size;
}
return o32.o32_psize;
}
/*****************************************************************************
Module()
in:
varies
out:
none
desc:
initializes the class variables
*****************************************************************************/
Module::Module(const string &file):File(file){
memset(&m_e32, 0, sizeof(m_e32));
m_o32_list.clear();
m_profile.m_function_list.clear();
memset(&m_profile, 0, sizeof(m_profile));
m_kernel_fixup_list.clear();
m_file_attributes = FILE_ATTRIBUTE_READONLY;
set_code_split(true);
set_module();
// information for relocation
m_e32_offset = 0;
m_o32_offset = 0;
m_vreloc = 0;
// map symbol information
m_TOC_offset = 0;
m_ROM_extensions = 0;
m_reset_vector = 0;
m_reset_vector_end = 0;
m_reset_vector_addr = 0;
}
/*****************************************************************************
init_kernel()
in:
fixup - wether or not we want to fix up the kernel
out:
none
desc:
sets some flags dealing with witch module is the kernel
*****************************************************************************/
bool Module::init_kernel(bool fixup, const Memory &ram_section){
if(name() == "nk.exe"){
m_flags |= FLAG_KERNEL;
if(fixup)
m_flags |= FLAG_KERNEL_FIXUP;
memory_iterator()->init_kernel();
}
else{
cerr << "Warning: No kernel module found" << endl;
}
assert(ram_section.type() == RAM_TYPE);
memset(&s_romhdr, 0, sizeof(s_romhdr));
s_romhdr.ulRAMStart = ram_section.address();
s_romhdr.ulRAMFree = ram_section.address();
s_romhdr.ulRAMEnd = ram_section.address() + ram_section.length();
return s_romhdr.ulRAMStart != 0 || s_romhdr.ulRAMEnd != 0;
}
/*****************************************************************************
sync_names()
in:
none
out:
boolean value indicating success
desc:
check if path name and file name are different:
m_name = nk.bin, m_release_path = d:\nk32.bin
optional m_build_path = public\projects\nkexe\SH3_rel\
if so, copy nk32.bin to nk.bin and copy the pdb and map file also.
*****************************************************************************/
bool Module::sync_names(bool profile, bool copy_files){
// check to see if the names differ
if(is_kernel() && profile){
m_release_path = lowercase(m_release_path);
if(m_release_path.find("nk.exe") != string::npos ||
m_release_path.find("nknodbg.exe") != string::npos)
m_release_path = m_release_path.substr(0, m_release_path.rfind("\\") + 1) + "nkprof.exe";
}
if(!copy_files)
return true;
if(m_name != m_release_path.substr(m_release_path.rfind("\\") + 1)){
string t_to = m_release_path.substr(0, m_release_path.rfind("\\") + 1) + m_name; // replace with short name
string t_from = m_release_path;
cout << "Copying " << t_from << " to " << t_to << " for debugger\n";
m_release_path = t_to; // update the qualified path with the new name
if(!CopyFile(t_from.c_str(), t_to.c_str(), false)){
cerr << "Error: Failed copying " << t_from << " to " << t_to << endl;
return false;
}
t_to.replace(t_to.rfind('.'), 4, ".pdb");
t_from.replace(t_from.rfind('.'), 4, ".pdb");
if(t_from != t_to && !CopyFile(t_from.c_str(), t_to.c_str(), false)){
// cerr << "Warning: Failed copying " << t_from << " to " << t_to << endl;
}
t_to.replace(t_to.rfind('.'), 4, ".map");
t_from.replace(t_from.rfind('.'), 4, ".map");
if(t_from != t_to && !CopyFile(t_from.c_str(), t_to.c_str(), false)){
// cerr << "Warning: Failed copying " << t_from << " to " << t_to << endl;
}
t_to.replace(t_to.rfind('.'), 4, ".rel");
t_from.replace(t_from.rfind('.'), 4, ".rel");
if(t_from != t_to && !CopyFile(t_from.c_str(), t_to.c_str(), false)){
// cerr << "Warning: Failed copying " << t_from << " to " << t_to << endl;
}
}
if(fixup_like_kernel()){
string reloc_file = m_release_path; // replace with short name
reloc_file.replace(reloc_file.rfind('.'), 4, ".rel");
if(GetFileAttributes(reloc_file.c_str()) == -1){
cerr << "Error: Module " << m_name << " reqested kernel fixup and couldn't find required .rel file\n";
return false;
}
}
return true;
}
/*****************************************************************************
add_sig_files()
in:
out:
desc:
*****************************************************************************/
bool Module::add_sig_files(FileList &file_list){
if(!needs_signing())
return true;
// add a signature file for this module, named in the form
// "module-suffix.sig"
string sig_name = name();
string release_path;
int pos = sig_name.rfind('.');
if(pos != string::npos)
sig_name[pos] = '-';
sig_name += ".sig";
release_path = m_release_path.substr(0, m_release_path.rfind("\\") + 1) + sig_name;
if(GetFileAttributes(release_path.c_str()) == -1){
ofstream sig_file(release_path.c_str(), ios::trunc);
if(sig_file.bad()){
cerr << "Error: Could not open '" << release_path << "' for writing\n";
return false;
}
sig_file << "This is a place holder for sig info";
sig_file.flush();
sig_file.close();
}
File file;
if(!file.set(sig_name, release_path, FILE_ATTRIBUTE_READONLY, memory_iterator(), m_compressor))
return false;
file_list.push_back(file);
m_signature_file = file_list.end();
m_signature_file--;
return true;
}
/*****************************************************************************
load()
in:
none
out:
boolean value indicating success
desc:
reads in the e32 structure, the o32 structures, the o32 data areas (if
any), and possible debuf fixup tables if we're the kernel
does a couple basic checks on the data also
*****************************************************************************/
bool Module::load(){
DWORD e32_ptr;
DWORD debug_offset;
ifstream file(m_release_path.c_str(), ios::in | ios::binary);
if(file.bad()){
cerr << "Error: Could not open '" << m_release_path << "' for reading\n";
return false;
}
file.seekg(0x3c); // e32 pointer offset
file.read((char *)&e32_ptr, sizeof(e32_ptr));
if(file.fail()){
cerr << "Error: Failed reading e32 pointer in module " << m_name << endl;
return false;
}
file.seekg(e32_ptr);
file.read((char *)&m_e32, sizeof(m_e32));
if(file.fail()){
cerr << "Error: Failed reading e32 structure in module " << m_name << endl;
return false;
}
if(!m_e32.e32_objalign){
cerr << "Warning: Page Size is zero, forcing to " << s_page_size << " in module " << m_name << endl;
m_e32.e32_objalign = s_page_size;
}
if(m_e32.e32_objalign != s_page_size){
cerr << "Error: only 4k page alignments supported at this time, found in module " << m_name << endl;
return false;
}
if(!m_e32.e32_vsize){
cerr << "Error: Invalid size specification (e32_vsize == 0) in module " << m_name << endl;
return false;
}
// might as well be thorough
if(m_e32.e32_magic[0] != 'P' ||
m_e32.e32_magic[1] != 'E' ||
m_e32.e32_magic[2] != '\0' ||
m_e32.e32_magic[3] != '\0' ){
cerr << "Error: Image signature invalid: found '" << m_e32.e32_magic
<< "' where '" << "PE" << "' expected in module " << m_name << endl;
return false;
}
bool resource_only = true;
// read all objects
for(int i = 0; i < m_e32.e32_objcnt; i++){
O32 o32;
file.seekg(e32_ptr + sizeof(m_e32) + i * sizeof(o32_obj));
file.read((char *)&o32, sizeof(o32_obj));
if(file.fail()){
cerr << "Error: Failed reading o32 structure in module " << m_name << endl;
return false;
}
if(o32.o32_rva <= m_e32.e32_unit[DEB].rva && m_e32.e32_unit[DEB].rva < o32.o32_rva + o32.o32_vsize)
debug_offset = o32.o32_dataptr - o32.o32_rva + m_e32.e32_unit[DEB].rva;
if(o32.o32_dataptr && o32.o32_psize){
file.seekg(o32.o32_dataptr);
file.read((char *)o32.data.user_fill(o32.o32_psize), o32.o32_psize);
if(file.fail()){
cerr << "Error: Failed reading o32 data in module " << m_name << endl;
return false;
}
}
if(o32.name() == ".rsrc")
o32.o32_flags &= ~IMAGE_SCN_MEM_WRITE;
else
resource_only = false;
if(m_flags & IMAGE_SCN_MEM_NOT_PAGED)
o32.o32_flags |= IMAGE_SCN_MEM_NOT_PAGED;
m_o32_list.push_back(o32);
}
if(resource_only){
fprintf(stderr, "Found a resource only dll %s\n", m_name.c_str());
m_flags |= FLAG_RESOURCE_ONLY;
}
// read in debugging info for kernel fixups, if appropriate
if(!s_cpu_id){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -