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

📄 module.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
      if(!is_kernel() && !fixup_like_kernel())
        assert(!"Error: Unknown fixup type encountered");
      break;
  }

  if(debug_show) printf("\n");

  return true;
}

/*****************************************************************************/
// MIPS relocation Types:
//
//  Relocation types are different in DEBUG fixups
//
//  Example                 COFF Fixup      DEBUG Fixup
//
//  lui     ax,0x8c05       4               4
//  jal     0x85049231      5               3
//  addiu   a0,a0,0xC610    2               5
//  0x8c049201              3               2
//
//#define IMAGE_REL_MIPS_ABSOLUTE           0
//#define IMAGE_REL_MIPS_REFHALF            01
//#define IMAGE_REL_MIPS_REFWORD            02
//#define IMAGE_REL_MIPS_JMPADDR            03
//#define IMAGE_REL_MIPS_REFHI              04
//#define IMAGE_REL_MIPS_REFLO              05
//
//
//#define IMAGE_REL_BASED_ABSOLUTE          0
//#define IMAGE_REL_BASED_HIGH              1
//#define IMAGE_REL_BASED_LOW               2
//#define IMAGE_REL_BASED_HIGHLOW           3
//#define IMAGE_REL_BASED_HIGHADJ           4
//#define IMAGE_REL_BASED_MIPS_JMPADDR      5
//
// PPC relocation Types:
// type 8  00568 81620000   lwz      r11,dpCurSettings(r2) ; dpCurSettings
// type 6  00590 4bfffa71   bl        ..NKDbgPrintfW ; NKDbgPrintfW     (subroutine call)
//
// type 16 13EFC 3C608002 lis        r3,[hia]HandleException
// type 17 13F00 386387E0 addi      r3,r3,[lo]HandleException
//
// type 18 (PAIR) always immediately follows type 16
//
// #define IMAGE_REL_PPC_REFHI  0x0010
// #define IMAGE_REL_PPC_REFLO  0x0011
// #define IMAGE_REL_PPC_PAIR    0x0012
//
/*****************************************************************************/

/*****************************************************************************
  fixup_nk()

  in:
    none
    
  out:
    boolean value indicating success

  desc:
    do special kernal fixups
 *****************************************************************************/
bool Module::fixup_nk(){
  assert(is_kernel());

#define DEBUG_IMAGE_REL_BASED_ABSOLUTE       0
#define DEBUG_IMAGE_REL_BASED_HIGH           1
#define DEBUG_IMAGE_REL_BASED_LOW            5
#define DEBUG_IMAGE_REL_BASED_HIGHLOW        2
#define DEBUG_IMAGE_REL_BASED_HIGHADJ        4
#define DEBUG_IMAGE_REL_BASED_MIPS_JMPADDR   3
#define DEBUG_IMAGE_REL_BASED_I386_HIGHLOW  20
#define DEBUG_IMAGE_REL_BASED_I386_HIGHLOW2  6
#define DEBUG_IMAGE_REL_BASED_PPC_REL24      6
#define DEBUG_IMAGE_REL_BASED_PPC_REFHI     16
#define DEBUG_IMAGE_REL_BASED_PPC_REFLO     17
#define DEBUG_IMAGE_REL_BASED_PPC_PAIR      18

  DWORD rva_delta = m_vreloc - m_e32.e32_vbase;

  DWORD *fixup_addr;
  WORD  *fixup_addr_hi;
  DWORD fixup_value;
  bool matched_ref_lo = false;

  for(unsigned i = 0; i < m_kernel_fixup_list.size(); i++){
    fixup_addr = (DWORD*)1;

    if(m_e32.e32_cpu == IMAGE_FILE_MACHINE_ARM || m_e32.e32_cpu == IMAGE_FILE_MACHINE_THUMB){
      switch(m_kernel_fixup_list[i].Type){
        case DEBUG_IMAGE_REL_BASED_MIPS_JMPADDR:
          break;
          
        case DEBUG_IMAGE_REL_BASED_HIGH:
          *(long UNALIGNED *)fixup_addr += get_rva_delta(m_kernel_fixup_list[i], rva_delta);
          break;
          
        default:
          fprintf(stderr, "Error: Not doing fixup type %d\n", m_kernel_fixup_list[i].Type);
          fprintf(stderr, "type %u, location %08x target %08x fixupop %08x\n", 
                  m_kernel_fixup_list[i].Type,
                  m_kernel_fixup_list[i].RvaLocation,
                  m_kernel_fixup_list[i].RvaTarget,
                  *fixup_addr);
          return false;
          break;
      }
      continue;
    }

    switch(m_kernel_fixup_list[i].Type){
      case DEBUG_IMAGE_REL_BASED_ABSOLUTE: 
        break;
      
      case DEBUG_IMAGE_REL_BASED_HIGH:
        fixup_addr_hi = (WORD *)fixup_addr;
        matched_ref_lo = true;
        break;

      case DEBUG_IMAGE_REL_BASED_LOW:
      case DEBUG_IMAGE_REL_BASED_PPC_REFLO:
        if(matched_ref_lo){
          fixup_value = (*fixup_addr_hi << 16) + *(WORD *)fixup_addr + get_rva_delta(m_kernel_fixup_list[i], rva_delta);
          *fixup_addr_hi = HIWORD(fixup_value + 0x8000);
          matched_ref_lo = false;
        }
        else
          fixup_value = *(WORD *)fixup_addr + get_rva_delta(m_kernel_fixup_list[i], rva_delta);

                *(WORD *)fixup_addr = LOWORD(fixup_value);
        break;
        
      case DEBUG_IMAGE_REL_BASED_I386_HIGHLOW:
        break;

      case DEBUG_IMAGE_REL_BASED_I386_HIGHLOW2:
        if(m_e32.e32_cpu & IMAGE_FILE_MACHINE_POWERPC){
          if(*fixup_addr & 0x2){
            fixup_value = *fixup_addr & 0x03fffffc;
            fixup_value += rva_delta;
            if(fixup_value & 0xfc000000){
              fprintf(stderr, "Error: fixup overflow at location %08x\n", m_kernel_fixup_list[i].RvaLocation);
              assert(!"Fatal error");
            }
            *fixup_addr = (*fixup_addr & 0xfc000003) | (fixup_value & 0x03fffffc);
          }
        }
        else{
          fixup_value = *fixup_addr & 0xff000000;
          *fixup_addr += get_rva_delta(m_kernel_fixup_list[i], rva_delta);
        }          
        break;
      case DEBUG_IMAGE_REL_BASED_HIGHLOW:
        *(long UNALIGNED *)fixup_addr += get_rva_delta(m_kernel_fixup_list[i], rva_delta);
        break;

      case DEBUG_IMAGE_REL_BASED_PPC_REFHI:
        if(m_e32.e32_cpu != IMAGE_FILE_MACHINE_POWERPC){
          fixup_value = *(WORD *)fixup_addr & 0x03ff;
          fixup_value = (fixup_value >> 5) | ((fixup_value & 0x1f) << 5);
          fixup_value = (fixup_value << 16) | *((WORD *)fixup_addr + 1);
          fixup_value += get_rva_delta(m_kernel_fixup_list[i], rva_delta) >> 2;
          *((WORD *)fixup_addr + 1) = LOWORD(fixup_value);
  
          fixup_value = HIWORD(fixup_value) & 0x3ff;
          fixup_value = (fixup_value >> 5) | ((fixup_value & 0x1f) << 5);
          *(WORD *)fixup_addr = LOWORD((*(WORD *)fixup_addr & 0x1c00) | fixup_value);
          break;
        }
        /* fall through for PowerPC's */

      case DEBUG_IMAGE_REL_BASED_HIGHADJ:
        assert(i + 1 < m_kernel_fixup_list.size());
        
        fixup_value = *(short UNALIGNED *)fixup_addr << 16;
        fixup_value += (long)(short)LOWORD(m_kernel_fixup_list[i].RvaTarget + m_kernel_fixup_list[i + 1].RvaTarget);
        fixup_value += get_rva_delta(m_kernel_fixup_list[i], rva_delta); // a REFHI has to be followed by a PAIR
        i++; // increment fixup list counter
        *(short UNALIGNED *)fixup_addr = HIWORD(fixup_value + 0x8000);
        break;

      case DEBUG_IMAGE_REL_BASED_MIPS_JMPADDR:
        fixup_value = (*fixup_addr & 0x03ffffff) + (rva_delta >> 2);
        *fixup_addr = (*fixup_addr & 0xfc000000) | (fixup_value & 0x3ffffff);
        break;

      default:
        fprintf(stderr, "Error: Not doing fixup type %d\n", m_kernel_fixup_list[i].Type);
        fprintf(stderr, "type %u, location %08x target %08x fixupop %08x\n", 
                m_kernel_fixup_list[i].Type,
                m_kernel_fixup_list[i].RvaLocation,
                m_kernel_fixup_list[i].RvaTarget,
                *fixup_addr);
        return false;
        break;
    }
  }
  
  return true;
}

bool Module::fixupvar(DWORD section, DWORD addr, DWORD value){
  if(!is_kernel()){
    fprintf(stderr, "Warning: All fixupvar elements must point to kernel addresses...ignored\n");
    return false;
  }

  O32List::iterator o32_itr = &m_o32_list[section];
  *(DWORD *)(o32_itr->data.ptr() + addr) = value;

  return true;
}

/*****************************************************************************
  remove_discardable_sections()

  in:
    none
    
  out:
    boolean value indicating success

  desc:
    Delete the discardable sections from the object list
 *****************************************************************************/
bool Module::remove_discardable_sections(){
  // remove discardable flag from resource section, we need to keep it
  for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++){
    if(o32_itr->o32_rva == m_e32.e32_unit[RES].rva){
      o32_itr->o32_flags &= ~IMAGE_SCN_MEM_DISCARDABLE;
      break;
    }
  }

  // remove all sections still marked as discardable
  o32_itr = m_o32_list.begin(); 
  while(o32_itr != m_o32_list.end())
    if(o32_itr->is_discardable())
      o32_itr = m_o32_list.erase(o32_itr);
    else
      o32_itr++;

  // adjust the object count to reflect the current count after removal
  m_e32.e32_objcnt = m_o32_list.size();
  
  return true;
}

/*****************************************************************************
  do_imports()

  in:
    module_list - may be needed for recursive searching
    
  out:
    boolean value indicating success

  desc:
    resolve import tables
 *****************************************************************************/
void Module::resolve_imports(ModuleList &module_list, bool error_late_bind){
  if(!m_e32.e32_unit[IMP].size){
    LAST_PASS_PRINT cout << "No imports for " << m_name << endl;
    return;
  }

  // Make imports section readonly since we're fixing it up
  for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++){
    if(o32_itr->o32_rva == m_e32.e32_unit[IMP].rva || o32_itr->o32_rva == m_e32.e32_unit[EXP].rva){
      o32_itr->o32_flags &= ~IMAGE_SCN_MEM_WRITE;
      break;
    }
  }

  ImpHdr *block_ptr, *block_start;

  block_ptr = block_start = (ImpHdr *)rva2ptr(m_e32.e32_unit[IMP].rva);
  while(block_ptr->imp_lookup){
    ModuleList::iterator mod_itr;

    // find dll name in module list
    mod_itr = find(module_list.begin(), module_list.end(), Module((char *)rva2ptr(block_ptr->imp_dllname)));
    if(mod_itr != module_list.end())
      mod_itr->set_static_ref_flag();
    else
      if (error_late_bind){
        cerr << "Error: Unable to do imports from " 
             << m_name << " to " << (char *)rva2ptr(block_ptr->imp_dllname) 
             << endl;
      }
      else{
        cerr << "Warning: Unable to do imports from " 
             << m_name << " to " << (char *)rva2ptr(block_ptr->imp_dllname) 
             << " - will late bind" << endl;
      }

    DWORD *ltptr = (DWORD *)rva2ptr(block_ptr->imp_lookup);
    DWORD *atptr = (DWORD *)rva2ptr(block_ptr->imp_address);

    while(*ltptr){
      if(mod_itr != module_list.end()){ // found it above
        if(*ltptr & 0x80000000)
          *atptr = mod_itr->resolve_imp_ord(module_list, *ltptr & ~0x80000000);
        else{ // see if the hint string is of any help
          ImpProc *impptr = (ImpProc *)rva2ptr(*ltptr);
          *atptr = mod_itr->resolve_imp_hint_str(module_list, impptr->ip_hint, string((char *)impptr->ip_name));
        }

        if(!*atptr){
          cerr << "Error: Fatal import error in " << m_name << endl;
          s_import_success_status = false;
        }
      } else // it's now statically loaded, forget about it
        *atptr = 0;
      
      ltptr++;
      atptr++;
    }
    
    block_ptr++;
  }
}

/*****************************************************************************
  compress()

  in:
    bool comp - global compression flag
    
  out:
    boolean value indicating success

  desc:
    (pretty self explanatory)
******************************************************************************/
bool Module::compress(bool comp){
  /* WARNING TO READERS
   *   you don't want to mess with any of the logic 
   *   in here if you don't absolutely have to :)
   */

  // no compression wanted or zero length
  if(!comp || !m_file_size){
    m_file_attributes &= ~FILE_ATTRIBUTE_COMPRESSED;

    //  truncate the kernel writable sections even if compression is off
    if(is_kernel() || fixup_like_kernel())
      for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
        if(o32_itr->is_writable())
          truncate_o32(*o32_itr);
    
    return true;
  }

  for(O32List::iterator o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++){
    //  I am REALLY sorry for this conditional!
    if(m_e32.e32_unit[IMP].rva == o32_itr->o32_rva || m_e32.e32_unit[EXP].rva == o32_itr->o32_rva){
      if(m_file_attributes & FILE_ATTRIBUTE_COMPRESSED)
        compress_o32(*o32_itr);
    }
    else if(is_kernel() || fixup_like_kernel()){
      if(o32_itr->is_writable())
        truncate_o32(*o32_itr); // don't compress, only truncate the kernel writable sections
    }
    else if(m_file_attributes & FILE_ATTRIBUTE_COMPRESSED ||
            o32_itr->is_writable()                   ||
            o32_itr->name() == ".pdata"              ||
            (o32_itr->name() == ".rsrc" && compress_resources())
           )
      compress_o32(*o32_itr);
  }

  return true;
}


/*****************************************************************************
 *****************************************************************************/
void Module::print_header(){
  static char *suppress = (suppress = getenv("ri_suppress_info")) ? strstr(suppress, "move") : NULL;
  if(suppress) return;
  
  LAST_PASS_PRINT printf("\nMODULES Section\n");
  LAST_PASS_PRINT printf("Module                 Section  Start     Length  psize   vsize   Filler\n");
  LAST_PASS_PRINT printf("---------------------- -------- --------- ------- ------- ------- ------\n");
}

/*****************************************************************************
  move_readonly_sections()

  in:
    reserve_list     - reserved memory list
    DWORD next_avail - next available stor

⌨️ 快捷键说明

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