📄 module.cpp
字号:
s_cpu_id = m_e32.e32_cpu;
s_page_size = page_size();
}
// check for pb_private_build in comment area
{
Data temp;
// skip past all o32 sections
DWORD offset = e32_ptr + sizeof(m_e32) + m_o32_list.size() * sizeof(o32_obj);
file.seekg(offset);
// read whole block
DWORD size = m_o32_list[0].o32_dataptr - offset;
if(size){
file.read((char*)temp.user_fill(size), size);
if(file.fail()){
cerr << "Error: Failed reading comment structure" << m_name << endl;
return false;
}
if(strstr((const char *)temp.ptr(), "pb_private_source"))
m_flags |= FLAG_WARN_PRIVATE_BITS;
}
}
if(is_kernel()){
// read in any kernel debug info if doing fixups
if(is_kernel_fixup_enabled() && m_e32.e32_unit[DEB].size){
IMAGE_DEBUG_DIRECTORY debug_dir = {0};
int debug_count = m_e32.e32_unit[DEB].size / sizeof(debug_dir);
// search for a fixup type debug dir
file.seekg(debug_offset);
for(int i = 0; i < debug_count && debug_dir.Type != IMAGE_DEBUG_TYPE_FIXUP; i++){
file.read((char *)&debug_dir, sizeof(debug_dir));
if(file.fail()){
cerr << "Error: Failed reading debug data in module " << m_name << endl;
return false;
}
}
if(debug_dir.Type != IMAGE_DEBUG_TYPE_FIXUP)
// cerr << "Warning: NK image debug type fixups not found, using standard fixups\n";
;
else{
// read in fixup data
FixupInfo fixup;
file.seekg(debug_dir.PointerToRawData);
for(unsigned i = 0; i < debug_dir.SizeOfData / sizeof(fixup); i++){
file.read((char *)&fixup, sizeof(fixup));
if(file.fail()){
cerr << "Error: Failed reading fixup data in module " << m_name << endl;
return false;
}
m_kernel_fixup_list.push_back(fixup);
}
}
}
}
return true;
}
/*****************************************************************************
set_load_address()
in:
DWORD addr - address to load module in memory
out:
none
desc:
sets the load address and also the e32 and o32 table load offsets
*****************************************************************************/
void Module::set_load_address(DWORD addr){
m_load_offset = addr;
DWORD size = page_size();
// Compute size of sections
for(O32List::const_iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
size += align_page(o32_itr->max_size());
// add in size of e32
m_e32_offset = m_load_offset + size;
size += sizeof(m_e32);
// add in size of o32's
m_o32_offset = m_load_offset + size;
}
/*****************************************************************************
get_load_size()
in:
none
out:
DWORD - size of module
desc:
returns module size as read from disk (ie. uncompressed)
*****************************************************************************/
DWORD Module::get_load_size(){
DWORD size = page_size();
// Compute size of sections
for(O32List::const_iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
size += align_page(o32_itr->max_size());
// add in size of e32
size += sizeof(m_e32);
// add in size of o32's
size += sizeof(o32_obj) * m_e32.e32_objcnt;
// round up to next page
return align_page(size);
}
/*****************************************************************************
set_base()
in:
MemoryList - list of reserved regions for kernel fixed up modules to look out for
out:
bool - invalid address
desc:
sets the relocation location for the module with a small check for
stripped kernels
dll - to next 64k aligned address DOWN!
kernel - to specified address
exe... if stripped - doesn't move
not stripped - moves to 0x10000
*****************************************************************************/
bool Module::set_base(const MemoryList &reserve_list){
static DWORD kernel_readonly_offset = 0;
// reinitialize some pass specific variables
if(is_kernel()){
kernel_readonly_offset = 0;
}
// if(is_resource_only())
// return true;
if(memory_iterator()->code_space_full)
set_code_split(false);
// give me some shorter names for all the references below
DWORD &code_addr = memory_iterator()->dll_code_start;
DWORD &data_addr = memory_iterator()->dll_data_start;
if(is_dll() && !fixup_like_kernel()){
if(is_code_split()){
// if we're going, old we can't go back
assert(!memory_iterator()->dll_data_split);
DWORD code_orig = code_addr;
DWORD data_orig = data_addr;
data_addr -= page_size();
for(O32List::const_iterator c_o32_itr = m_o32_list.begin(); c_o32_itr != m_o32_list.end(); c_o32_itr++){
if(c_o32_itr->is_writable() && !c_o32_itr->is_shared())
data_addr -= align_page(c_o32_itr->max_size());
code_addr -= align_page(c_o32_itr->max_size());
}
code_addr -= align_page(sizeof(e32_exe) + sizeof(o32_obj) * m_e32.e32_objcnt);
data_addr &= 0xfffff000; // round DOWN to next PAGE boundry
code_addr &= 0xffff0000; // round DOWN to next 64k boundry
if(code_addr < memory_iterator()->dll_code_bottom){
code_addr = code_orig;
data_addr = data_orig;
set_code_split(false);
memory_iterator()->code_space_full = true;
goto OLD_FIXUP;
}
DWORD data = data_addr + page_size();
DWORD code = code_addr + page_size();
for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
if(o32_itr->is_writable() && !o32_itr->is_shared()){
o32_itr->o32_realaddr = data;
data += align_page(o32_itr->max_size());
code += align_page(o32_itr->max_size());
}
else{
o32_itr->o32_realaddr = code;
code += align_page(o32_itr->max_size());
}
}
else{
OLD_FIXUP:
if(memory_iterator()->code_space_full){
cout << "Code space full, fixing up " << m_name << " to ram space\n";
}
// add in gaps for first low module and set split address
if(!memory_iterator()->dll_data_split){
data_addr -= memory_iterator()->dll_data_gap;
data_addr &= 0xffff0000; // round DOWN to next 64k boundry
memory_iterator()->dll_data_split = data_addr;
data_addr -= memory_iterator()->dll_gap;
}
data_addr -= get_load_size() - page_size();
data_addr &= 0xffff0000; // round DOWN to next 64k boundry
m_vreloc = data_addr;
}
}
else if(is_kernel()){
m_vreloc = memory_iterator()->address();
kernel_readonly_offset = page_size();
for(unsigned i = 0; i < m_o32_list.size(); i++)
if(!m_o32_list[i].is_writable() && !m_o32_list[i].is_discardable())
kernel_readonly_offset += align_page(m_o32_list[i].min_size());
}
else if(fixup_like_kernel()){
m_vreloc = memory_iterator()->address() + kernel_readonly_offset;
kernel_readonly_offset += page_size();
for(O32List::const_iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
if(!o32_itr->is_writable() && !o32_itr->is_discardable())
kernel_readonly_offset += align_page(o32_itr->min_size());
DWORD size = kernel_readonly_offset - (m_vreloc - memory_iterator()->address());
DWORD temp = align_page(Memory::find_next_gap(reserve_list, m_vreloc, size));
if(m_vreloc != temp){
m_vreloc = temp;
kernel_readonly_offset = temp + size;
}
}
else if(m_e32.e32_imageflags & IMAGE_FILE_RELOCS_STRIPPED)
m_vreloc = m_e32.e32_vbase;
else
m_vreloc = 0x10000;
if(m_vreloc)
for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
o32_itr->o32_realaddr = m_vreloc + o32_itr->o32_rva;
// checking to make sure a stripped kernel is in some arbitrary range
if(is_kernel() && m_e32.e32_imageflags & IMAGE_FILE_RELOCS_STRIPPED &&
(m_vreloc < 0x10000 || m_vreloc > 0x400000)){
cerr << "Error: Module " << m_name << " relocations stripped, remove -fixed from link command\n";
return false;
}
return true;
}
/*****************************************************************************
verify_cpu()
in:
none
out:
bool - indicating good status
desc:
checks to make sure the the cpu the module was compiled for is compatible
with that which the kernel was compiled with
*****************************************************************************/
bool Module::verify_cpu() const{
if(ignore_cpu())
return true;
// Allow ARM & Strongarm to mix, even though on SA1100 it won't work. Even though we can't
// detect this, the kernel will detect it and fail to load something that he can't handle.
if(m_e32.e32_cpu != s_cpu_id &&
!m_e32.e32_unit[RS4].rva &&
!(m_e32.e32_cpu == IMAGE_FILE_MACHINE_SH3 && s_cpu_id == IMAGE_FILE_MACHINE_SH3DSP) &&
!(m_e32.e32_cpu == IMAGE_FILE_MACHINE_SH3 && s_cpu_id == IMAGE_FILE_MACHINE_SH4 ) &&
!(m_e32.e32_cpu == IMAGE_FILE_MACHINE_R4000 && s_cpu_id == IMAGE_FILE_MACHINE_MIPS16) &&
!(m_e32.e32_cpu == IMAGE_FILE_MACHINE_ARM && s_cpu_id == IMAGE_FILE_MACHINE_THUMB )
){
map<DWORD, string> cpu_id_list;
cpu_id_list[IMAGE_FILE_MACHINE_I386] = "I386";
cpu_id_list[IMAGE_FILE_MACHINE_R3000] = "R3000";
cpu_id_list[IMAGE_FILE_MACHINE_R4000] = "R4000";
cpu_id_list[IMAGE_FILE_MACHINE_MIPS16] = "mips";
cpu_id_list[IMAGE_FILE_MACHINE_ALPHA] = "ALPHA";
cpu_id_list[IMAGE_FILE_MACHINE_SH3] = "SH3";
cpu_id_list[IMAGE_FILE_MACHINE_SH4] = "SH4";
cpu_id_list[IMAGE_FILE_MACHINE_POWERPC] = "PowerPC";
cpu_id_list[IMAGE_FILE_MACHINE_ARM] = "ARM";
cpu_id_list[IMAGE_FILE_MACHINE_THUMB] = "Thumb";
cpu_id_list[IMAGE_FILE_MACHINE_UNKNOWN] = "Unknown";
cerr << "Error: Module " << m_name << " built for " << cpu_id_list[m_e32.e32_cpu]
<< ", kernel built for " << cpu_id_list[s_cpu_id] << endl;
return false;
}
return true;
}
/*****************************************************************************
get_symbols()
in:
none
out:
bool - value indicating success
desc:
Load the symbol information
*****************************************************************************/
bool Module::get_symbols(bool profile_all, MemoryList &memory_list){
if(!m_e32.e32_symcount) // mo symbols in module, use map file
return get_map_symbols(profile_all, memory_list);
// open the file
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;
}
// seek to the start of the symbol table
file.seekg(m_e32.e32_symtaboff);
// read symbol table
SymbolList symbol_list;
for(unsigned i = 0; i < m_e32.e32_symcount; i++){
COFF_Symbol coff_sym;
file.read((char *)&coff_sym, sizeof(coff_sym));
if(file.fail()){
cerr << "Error: Failed reading COFF symbol structure in module " << m_name << endl;
return false;
}
symbol_list.push_back(coff_sym);
}
// read the length of the string table (imediatly follows the symbol table)
DWORD string_table_len = 0;
Data string_table;
file.read((char *)&string_table_len, sizeof(string_table_len));
if(file.fail()){
cerr << "Error: Failed reading string table length in module " << m_name << endl;
return false;
}
// read the table itself (imediatly follows the length)
if(string_table_len){
file.read((char *)string_table.user_fill(string_table_len), string_table_len);
if(file.fail()){
cerr << "Error: Failed reading string table in module " << m_name << endl;
return false;
}
}
file.close();
// check each symbol against the string table names
for(i = 0; i < symbol_list.size(); i++){
if(symbol_list[i].usType == 0x20 ||
(profile_all && symbol_list[i].ulValue >= m_e32.e32_codebase && symbol_list[i].ulValue < m_e32.e32_database)){
string buffer;
// get the name either from the Coff symbol or string table lookup
if(symbol_list[i].dwNULL != NULL)
buffer.assign((char *)symbol_list[i].szName, 8);
else{
assert(!string_table.empty());
buffer = (char *)string_table.ptr() + symbol_list[i].dwPosLow - 4;
}
// skip strings with .'s in them
if(buffer.find('.') != string::npos)
continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -