⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 module.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// This source code is licensed under Microsoft Shared Source License
// Version 1.0 for Windows CE.
// For a copy of the license visit http://go.microsoft.com/fwlink/?LinkId=3223.
//
#include "module.h"
#include "..\parser\token.h"

#include "compress.h"
#include "romsig.h"

/*****************************************************************************
  get_map_symbols()

  in:
    bool       return mangled names if profile_all is set
    MemoryList &memory_list
    
  out:
    boolean value indicating success

  desc:
    retrieves all the info for the symbols from the .map file, if it exists
 *****************************************************************************/
bool Module::get_map_symbols(bool profile_all, MemoryList &memory_list){
  string map_file = m_release_path;

  map_file.replace(map_file.rfind('.'), 4, ".map");

  // used to make sure the file exists
  if(GetFileAttributes(map_file.c_str()) == -1)
    return true; // don't care if there is a map file or not

  // open
  ifstream file(map_file.c_str(), ios::in);
  if(file.bad()){
    cerr << "Error: Could not open '" << map_file << "' for reading\n";
    return false;
  }

  string line;

  // skip to start of symbols
  while(!file.eof() && line.find("Publics by Value") == string::npos)
    getline(file, line, '\n');

  // start processing and seaching tokens
  string token;
  while(!file.eof()){
    getline(file, line, '\n');

    // skip lines with no symbol information
    if(line.substr(0, 3) != " 00" || line[5] != ':')
      continue;

    // envvar for backwards compatability
    static string delim = getenv("romimagenotrunc") || profile_all ? " " : " @";
    token = Token::get_token(line, 21, delim);

        DWORD sec_number = Token::get_hex_value(line.substr(1, 4)) - 1;
    DWORD sec_offset = Token::get_hex_value(line.substr(6, 8)) + page_size();
    
    if(line.find(" f ") != string::npos){
      Function f;
      f.name = token;
      f.address = Token::get_hex_value(line.substr(6, 8));
      m_profile.m_function_list.push_back(f);
    }
    else if(sec_number >= 0 && sec_number < m_o32_list.size() && !m_o32_list[sec_number].is_writable() && token[0] != '?'){
      Function f;
      f.name = token;
      f.address = Token::get_hex_value(line.substr(6, 8));
      m_profile.m_function_list.push_back(f);
    }
   
    check_special_symbol(token, sec_number, sec_offset, memory_list);
  }

  return true;  
}

/*****************************************************************************
  check_special_symbol()

  in:
    MemoryList &memory_list
    
  out:
    none

  desc:
    looks for certain special symbol names to set state variables
 *****************************************************************************/
void Module::check_special_symbol(string token, DWORD o32_section, DWORD offset, MemoryList &memory_list){
  if(token[0] == '_')
    token.erase(0, 1);

  if(token == "RomExt")
    m_ROM_extensions = memory_iterator()->address() + offset + m_load_offset;

  if(token == "ResetVector")
    m_reset_vector = (DWORD *)(m_o32_list[0].data.ptr() + offset - page_size());

  if(token == "ResetVectorEnd")
    m_reset_vector_end = (DWORD *)(m_o32_list[0].data.ptr() + offset - page_size());
  
  if(token == "ResetVectorAddr")
    m_reset_vector_addr = (DWORD *)(m_o32_list[0].data.ptr() + offset - page_size());
  
  if(token == "KdDebuggerEnabled")
    m_flags |= FLAG_KERNEL_DEBUGGER;

  if(is_kernel()){
    if(token == "pTOC"){
      m_TOC_offset = offset + m_load_offset;  // doesn't get load offset added, because only compared with rva later
      LAST_PASS_PRINT printf("Found pTOC at %08x\n", m_TOC_offset);
    }

    if(needs_signing()){
      if(token == "OEMIoControl")
        s_oem_io_control = offset + m_load_offset - page_size();
    }

    if(o32_section != -1)
      for(MemoryList::iterator mem_itr = memory_list.begin(); mem_itr != memory_list.end(); mem_itr++)
        if(mem_itr->type() == FIXUPVAR_TYPE)
          if(mem_itr->name() == token){
            static char *debug_show = (debug_show = getenv("ri_debug_info")) ? strstr(debug_show, "fixupvar") : NULL;

            mem_itr->fixupvar_section = o32_section;
            mem_itr->Address::set(offset + m_load_offset - page_size(), mem_itr->length());

            if(debug_show) printf("FixupVar %s is at %08x\n", mem_itr->name().c_str(), mem_itr->address());
          }
  }
}

/*****************************************************************************
  rva2ptr()

  in:
    DWORD relative vertual address to resolve
    
  out:
    DWORD address of data - NULL indicates failure

  desc:
    takes the rva and searches to see which objects range it falls into and 
    then returns a pointer the the apropriate location in the data
 *****************************************************************************/
DWORD Module::rva2ptr(DWORD rva) const{
  for(O32List::const_iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
    if((!o32_itr->o32_psize && o32_itr->o32_rva == rva) || 
       (o32_itr->o32_rva <= rva && rva < o32_itr->o32_rva + o32_itr->o32_psize))
      return (DWORD)o32_itr->data.ptr() + rva - o32_itr->o32_rva;

  fprintf(stderr, "Error: Could not find rva %08x in %s\n", rva, m_name.c_str());
  for(DWORD i = 0; i < m_o32_list.size(); i++)
    fprintf(stderr, "o32[%d].o32_rva = %08x (len = %08x)\n", i, m_o32_list[i].o32_rva, m_o32_list[i].o32_psize);

  assert(!"rva2ptr() error");

  return 0;
}

/*****************************************************************************
  nk_fixup_rva()

  in:
    DWORD fixup_addr - address to be fixed up
    DWORD base       - base memory offset
    
  out:
    DWORD - fixed up address or origional if no fixup found

  desc:
    fixes up kernel rva's
 *****************************************************************************/
DWORD Module::fixup_rva_nk(DWORD fixup_addr){
  DWORD orig_fixup_addr = fixup_addr;

  // Actual section starting rva after readonly sections have been moved to start of image
  DWORD next_avail = m_o32_list[0].o32_rva;

    fixup_addr = (fixup_addr & 0x00FFFFFF) - (m_vreloc & 0x00FFFFFF);

  for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end() && fixup_addr >= o32_itr->o32_rva + o32_itr->max_size(); o32_itr++){
    // address found
    if((o32_itr + 1) != m_o32_list.end() && fixup_addr < (o32_itr + 1)->o32_rva)
      break;

    if(!o32_itr->is_writable())
      next_avail += align_page(o32_itr->min_size());
  }

  if(o32_itr == m_o32_list.end()){
#if 0   // debug check for sections   
    static bool once = true;

    if(once){
      fprintf(stderr, "Error: Could not find rva %08x in %s\n", fixup_addr, m_name.c_str());
      for(int i = 0; i < m_o32_list.size(); i++)
        fprintf(stderr, "o32[%d].o32_rva = %08x (len = %08x)\n", i, m_o32_list[i].o32_rva, m_o32_list[i].o32_psize);

      once = false;
    }
#endif
    
    fprintf(stderr, "Section not found for %8x fixing up %s\n", fixup_addr, name().c_str());
    return orig_fixup_addr;
  }

  if(!o32_itr->is_writable())
    return orig_fixup_addr - (o32_itr->o32_rva - next_avail);

  if(fixup_addr == m_TOC_offset){
    fprintf(stderr, "NKFixupRVA: target %8x is in section %s offset=%8x - is TOC not changed!\n",
            fixup_addr, m_name.c_str(), o32_itr->o32_rva + o32_itr->o32_dataptr);

    return orig_fixup_addr;
  }

  fixup_addr = fixup_addr - o32_itr->o32_rva + o32_itr->o32_dataptr;

  // Reset top bit to be same as original fixup address
  // Note: this scheme assumes a 1:1 physical to virtual address correspondence, where 0x80000000 <-> 0x00000000
  if(!(orig_fixup_addr & 0x80000000))
    fixup_addr &= 0x7fffffff;

  return fixup_addr;
}

/*****************************************************************************
 *****************************************************************************/
DWORD Module::get_rva_delta(const FixupInfo &kernel_fixup, DWORD rva_delta){
  if(m_o32_list[0].is_writable())
    assert(!"Error: First section of NK must be READONLY!");

  DWORD next_avail = m_o32_list[0].o32_rva; // actual section starting rva after relocate_image() is called
  for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end() && (kernel_fixup.RvaTarget < o32_itr->o32_rva || kernel_fixup.RvaTarget >= o32_itr->o32_rva + o32_itr->o32_vsize); o32_itr++){
    if((o32_itr + 1) != m_o32_list.end() && kernel_fixup.RvaTarget >= o32_itr->o32_rva && kernel_fixup.RvaTarget < (o32_itr + 1)->o32_rva)
      break;

    if(!o32_itr->is_writable())
      next_avail += align_page(o32_itr->min_size());
  }

  if(o32_itr == m_o32_list.end()){
    fprintf(stderr, "Section not found for %8x\n", kernel_fixup.RvaTarget);
    // assert(0); // I don't think a return is apropriate here! but I'm going to let it go for now.
  }

  if(!o32_itr->is_writable()){
    if(o32_itr->o32_rva != next_avail)
      return rva_delta - (o32_itr->o32_rva - next_avail);

    return rva_delta;
  }

  return (DWORD)o32_itr->data.ptr() - m_e32.e32_vbase - o32_itr->o32_rva;
}

/*****************************************************************************
  addr_from_eat()

  in:
    module_list - modules that may be needed for recursive searching
    DWORD   eat - eat address to find
    
  out:
    DWORD - result or zero if not found

  desc:
    get the address from the export address table
 *****************************************************************************/
DWORD Module::addr_from_eat(const ModuleList &module_list, DWORD eat) const{
  const DWORD SECTION_MASK = 0x03F;
  const DWORD VA_SECTION   = 25;
  
  if(eat < m_e32.e32_unit[EXP].rva || eat >= m_e32.e32_unit[EXP].rva + m_e32.e32_unit[EXP].size){
    DWORD ptr = m_vreloc;

    if(ptr & 0x80000000) 
      ptr &= ~(SECTION_MASK << VA_SECTION);

    return eat + ptr;
  }

  string filename = (char *)rva2ptr(eat);
  string str = filename;

  if(filename.find('.')){
    filename.erase(filename.find('.'));
    str.erase(0, str.find('.') + 1);
  }

  for(ModuleList::const_iterator mod_itr = module_list.begin(); mod_itr != module_list.end(); mod_itr++){
    string modname = mod_itr->name();

    modname = modname.substr(0, modname.find('.'));

    if(modname == filename)
      if(str[0] == '@')
        return mod_itr->resolve_imp_ord(module_list, atoi(str.c_str() + 1));
      else
        return mod_itr->resolve_imp_str(module_list, str);
  }

  cerr << "Error: Unresolved external: " << filename << endl;

  return 0;
}

/*****************************************************************************
  resolve_imp_ord()

  in:
    module_list - modules that may be needed for recursive searching
    DWORD   ord - ordinal to find the address for
    
  out:
    DWORD - address of function for ordinal or NULL for failure

  desc:
    find the address of a function specified by ordinal number
 *****************************************************************************/
DWORD Module::resolve_imp_ord(const ModuleList &module_list, DWORD ord) 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);

  DWORD hint = ord - expptr->exp_ordbase;
  DWORD ret = 0;
  
  if(hint <= expptr->exp_eatcnt)
    ret = addr_from_eat(module_list, eatptr[hint]);

  if(!ret){
    cerr << "Error: Can't find import " << ord << " in " << m_name << endl;
  }

  return ret;
}

/*****************************************************************************
  resolve_imp_str()

  in:
    module_list - modules that may be needed for recursive searching
    string str  - name of function to resolve
    
  out:
    DWORD - address of function named, NULL for failure

  desc:
    resolve a funciton by name
 *****************************************************************************/
DWORD Module::resolve_imp_str(const ModuleList &module_list, 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);
  char **nameptr = (char **)rva2ptr(expptr->exp_name);
  DWORD *eatptr = (DWORD *)rva2ptr(expptr->exp_eat);
  WORD *ordptr = (WORD *)rva2ptr(expptr->exp_ordinal);

  for(unsigned i = 0; i < expptr->exp_namecnt; i++)
    if(str == (char *)rva2ptr((DWORD)nameptr[i]))
      break;
  
  // found it
  if(i != expptr->exp_namecnt)
    return addr_from_eat(module_list, eatptr[ordptr[i]]);
  
  cerr << "Error: Can't find import " << str << " in " << m_name << endl;

  return 0;
}

/*****************************************************************************
  resolve_imp_hint_ord()

  in:
    module_list - modules that may be needed for recursive searching
    DWORD hint  - type of string provided for the hint
    string str  - using in cojunction with a hint to determin function resolution
    
  out:
    DWORD - address of function, NULL indicates failure

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -