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

📄 module.cpp

📁 WinCE5.0部分核心源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:

      // if NOT profiling all then skip lines with a $ and lines beginning with L#
      if(!profile_all)
        if(buffer.find('$') != string::npos || (buffer[0] == 'L' && isdigit((unsigned char)buffer[1])))
          continue;

      // do this to whatever gets through the previous checks
      Function f;
      f.name = buffer;
      f.address = symbol_list[i].ulValue;
      m_profile.m_function_list.push_back(f);      
    }
  }       

  // sorts them in address order (as if they had been read from a map file)
  sort(m_profile.m_function_list.begin(), m_profile.m_function_list.end());

    for(i = 0; i < m_profile.m_function_list.size(); i++){
      }

  // search the symbol list against special symbols
  for(i = 0; i < symbol_list.size(); i++){
        if(symbol_list[i].usType != 0x20 && symbol_list[i].cClass == 2){
      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;
      }

      check_special_symbol(buffer, -1, symbol_list[i].ulValue, memory_list);
    }
  }  

  return true;
}

/*****************************************************************************
  relocate_image()

  in:
    none
    
  out:
    boolean value indicating success

  desc:
    relocates module load and bin file locations
 *****************************************************************************/
bool Module::relocate_image(){
  DWORD offset = page_size();

  for(O32List::iterator itr = m_o32_list.begin(); itr != m_o32_list.end(); itr++){
    // set section header data pointer
    itr->o32_dataptr = memory_iterator()->address() + m_load_offset + offset;
    
    offset += align_page(itr->max_size());

    if((is_kernel() || fixup_like_kernel()) && is_kernel_fixup_enabled() && itr->is_writable()){
      if(itr->name() == ".KDATA"){
        DWORD aligned_free;
        
        if(is_arm())
          aligned_free = align_64k(Module::s_romhdr.ulRAMFree);
        else
          aligned_free = align_16k(Module::s_romhdr.ulRAMFree);

        if(aligned_free != Module::s_romhdr.ulRAMFree)
          Module::s_romhdr.ulRAMFree = aligned_free;
      }

      itr->o32_dataptr = Module::s_romhdr.ulRAMFree;

      Module::s_romhdr.ulRAMFree += align_page(itr->max_size());
    }
  }

  return true;
}

/*****************************************************************************
  fixup()

  in:
    none
    
  out:
    boolean value indicating success

  desc:
    fix up tables for relocated module
 *****************************************************************************/
bool Module::fixup(){
  // kernel is special
  if(is_kernel() && is_kernel_fixup_enabled() && m_kernel_fixup_list.size())
    return fixup_nk();
  
  // no relocations
  if(!m_e32.e32_unit[FIX].size){
    if(is_kernel() && is_kernel_fixup_enabled())
      cerr << "Warning: No fixup information for NK.  NK linkr command /FIXED:NO may be required\n";

    return true;
  }

  if(fixup_like_kernel() && !is_code_split()){
    cerr << "Error: Module " << m_name << " reqested kernel fixup but has an invalid .rel file or"
         << " some other condition that prevents the code section from being split\n";
    
    exit(1);
  }

  static char *debug_show = (debug_show = getenv("ri_debug_info")) ? strstr(debug_show, "fixups") : NULL;
  
  if(debug_show) printf("Fixups for %s\n", m_name.c_str());

  if(!is_code_split())
    return fixup_no_split();

  // setup relocation filename
  string reloc_file = m_release_path;
  reloc_file.replace(reloc_file.rfind('.'), 4, ".rel");
  if(GetFileAttributes(reloc_file.c_str()) == -1)
    return false;

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

  string line;
  DWORD time_stamp;

  getline(file, line, '\n');
  if(sscanf(line.c_str(), "Timestamp: %08X", &time_stamp) != 1 || time_stamp != m_e32.e32_timestamp){
    if(is_kernel() || fixup_like_kernel()){
      cerr << "Error: Mismatched time stamp on .rel file for module " << m_name << " requesting kernel fixup.  Valid .rel file is required for kernel fixups.\n";
      exit(1);
    }
    
    cerr << "Warning: Mismatched time stamp on .rel file for module " << m_name << endl;
    return false;
  }

  while(!file.eof()){
    WORD  reloc_type;
    WORD  reloc_section;
    DWORD reloc_offset;
    DWORD reloc_lowaddr;

    getline(file, line, '\n');
    if(sscanf(line.c_str(), "%04X %04X %08X %08X", &reloc_type, &reloc_section, &reloc_offset, &reloc_lowaddr) != 4)
      continue;

    if(debug_show) printf("%s ", line.c_str());
  
    assert(reloc_section >= 1 && reloc_section <= m_o32_list.size());

    reloc_section--; // I'm zero based

    O32List::iterator o32_itr = m_o32_list.end();
    
    if(o32_itr == m_o32_list.end() || 
       o32_itr->o32_rva > reloc_offset ||
       o32_itr->o32_rva + o32_itr->o32_vsize <= reloc_offset){

      for(o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
        if(o32_itr->o32_rva <= reloc_offset &&
           o32_itr->o32_rva + o32_itr->o32_vsize > reloc_offset)
          break;

      assert(o32_itr != m_o32_list.end());
    }

    DWORD offset = m_o32_list[reloc_section].o32_realaddr - m_e32.e32_vbase - m_o32_list[reloc_section].o32_rva;
    DWORD *fixup_addr = (DWORD*)(reloc_offset - o32_itr->o32_rva + (DWORD)o32_itr->data.ptr());

    apply_fixup(reloc_type, fixup_addr, offset, (WORD)reloc_lowaddr);
  }

  return true;
}

/*****************************************************************************
  do_fixups()

  in:
    none
    
  out:
    boolean value indicating success

  desc:
    fix up tables for relocated module
 *****************************************************************************/
bool Module::fixup_no_split(){
  assert(!fixup_like_kernel());
  
  DWORD offset = m_vreloc - m_e32.e32_vbase;

  // don't really have any clue about what is going on here.  Just following the source code.
  info *block_ptr = (info*)rva2ptr(m_e32.e32_unit[FIX].rva);
  for(info *block_start = block_ptr; 
      (DWORD)block_ptr < (DWORD)block_start + m_e32.e32_unit[FIX].size && block_ptr->size;
      block_ptr = (info*)((DWORD)block_ptr + block_ptr->size)){

    O32List::iterator o32_itr = m_o32_list.end();
    
    for(WORD *current_ptr = (WORD*)((DWORD)block_ptr + sizeof(info)); 
        (DWORD)current_ptr < (DWORD)block_ptr + block_ptr->size; 
        current_ptr++){

      WORD current_offset = *current_ptr & 0xfff;

      // nothing here to fix
      if(!current_offset && !block_ptr->rva){
        current_ptr++;
        continue;
      }

      if(o32_itr == m_o32_list.end() || 
         o32_itr->o32_rva > block_ptr->rva + current_offset ||
         o32_itr->o32_rva + o32_itr->o32_vsize <= block_ptr->rva + current_offset){

        for(o32_itr = m_o32_list.begin(); o32_itr != m_o32_list.end(); o32_itr++)
          if(o32_itr->o32_rva <= block_ptr->rva + current_offset &&
             o32_itr->o32_rva + o32_itr->o32_vsize > block_ptr->rva + current_offset)
            break;

        assert(o32_itr != m_o32_list.end());
      }

      DWORD *fixup_addr = (DWORD*)(block_ptr->rva - o32_itr->o32_rva + current_offset + (DWORD)o32_itr->data.ptr());
      WORD   fixup_type = (*current_ptr >> 12) & 0xf;

      if(fixup_type == IMAGE_REL_BASED_HIGHADJ)
        ++current_ptr;

      static char *debug_show = (debug_show = getenv("ri_debug_info")) ? strstr(debug_show, "fixups") : NULL;
      
      if(debug_show) printf("%04x %04x %08x %08x ", fixup_type, 1, block_ptr->rva + current_offset, fixup_type == IMAGE_REL_BASED_HIGHADJ ? *current_ptr : 0);

      apply_fixup(fixup_type, fixup_addr, offset, LOWORD(*current_ptr));
    }
  }

  return true;
}
  
/*****************************************************************************/
bool Module::apply_fixup(WORD type, DWORD *addr, DWORD offset, WORD low_addr){
  static WORD *fixup_addr_hi = NULL;
  static bool matched_ref_lo = false;

  struct Type4Fixup{ 
    DWORD addr;
    WORD  addr_lo;
  };

  const DWORD MAX_TYPE4_NEST = 16;
  static DWORD num_type4 = 0;
  static Type4Fixup type4_fixup[MAX_TYPE4_NEST];

  DWORD value;
  static char *debug_show = (debug_show = getenv("ri_debug_info")) ? strstr(debug_show, "fixups") : NULL;
  
  switch(type){
    // MIPS relocation types:

    // No location is necessary, reference is to an absolute value
    case IMAGE_REL_BASED_ABSOLUTE:
      break;

    // Reference to the upper 16 bits of a 32-bit address.
    // Save the address and go to get REF_LO paired with this one
    case IMAGE_REL_BASED_HIGH:
      fixup_addr_hi = (WORD*)addr;
      matched_ref_lo = true;
      break;

    // Direct reference to a 32-bit address. With RISC
    // architecture, such an address cannot fit into a single
    // instruction, so this reference is likely pointer data
    // Low - (16-bit) relocate high part too.
    case IMAGE_REL_BASED_LOW:
      if(debug_show) printf("fixup %08x -> ", *addr);

      if((is_kernel() || fixup_like_kernel()) && num_type4){
        for(unsigned i = 0; i < num_type4; i++)
          if(*(WORD *)addr == type4_fixup[i].addr_lo)
            break;

        if(i >= num_type4)
          assert(!"Error: BASED_LOW fixup nested too deap!");
        
        value = type4_fixup[i].addr;
        memcpy(&type4_fixup[i], &type4_fixup[i + 1], (num_type4 - i) * sizeof(Type4Fixup));
        num_type4--;
      }
      else if(matched_ref_lo){
        value = (DWORD)(*fixup_addr_hi << 16) + *(WORD*)addr + offset;
        
        *fixup_addr_hi = HIWORD(value + 0x8000);
        matched_ref_lo = false;
      }          
      else{
        value = *(short *)addr + offset;

        if(is_kernel() || fixup_like_kernel())
          assert(!"Error: kernel must have matched BASED_HIGH/BASED_LOW fixup pair");
      }

      *(WORD*)addr = (WORD)(value & 0xffff);

      if(debug_show) printf("%08x", *addr);

      break;

    // Word - (32-bits) relocate the entire address.
    case IMAGE_REL_BASED_HIGHLOW:
      if(debug_show) printf("fixup %08x -> ", *addr);
        
      if(is_kernel() || fixup_like_kernel()){
        *addr = fixup_rva_nk(*addr + offset);
      }
      else
        *addr += offset;

      if(debug_show) printf("%08x", *addr);

      break;

    // 32 bit relocation of 16 bit high word, sign extended
    case IMAGE_REL_BASED_HIGHADJ:
      if(debug_show) printf("fixup %08x -> ", *addr);
      
      if(is_kernel() || fixup_like_kernel()){
        value = fixup_rva_nk((*(short UNALIGNED *)addr << 16) + (long)(short)low_addr + offset);

        if(num_type4 < MAX_TYPE4_NEST){
          type4_fixup[num_type4].addr = value;
          type4_fixup[num_type4].addr_lo = low_addr;
          num_type4++;
        }
        else{
          cerr << "Error: exceeded type 4 fixup nesting level in module " << m_name << endl;
          printf("addr %08x low_addr %04x\n", (DWORD)addr, low_addr);
          return false;
        }

        *(short UNALIGNED *)addr = HIWORD(value + 0x8000);
      }
      else
        *(short UNALIGNED *)addr += HIWORD((long)(short)low_addr + offset + 0x8000);

      if(debug_show) printf("%08x", *addr);

      break;

    // Reference to the low portion of a 32-bit address.
    // jump to 26 bit target (shifted left 2)

    // weird dll in mips16 land uses absolute address for jumps while the rest of the world
    // uses relative.  Therefore we had to come up with way to add the base in and not mess up
    // when the base was already in.
    case IMAGE_REL_BASED_MIPS_JMPADDR:
      if(debug_show) printf("fixup %08x -> ", *addr);

      value = (*addr & 0x03ffffff) + (offset >> 2);
      *addr = (*addr & 0xfc000000) | (value & 0x03ffffff);

      if(debug_show) printf("%08x", *addr);
      break;

    // MIPS16 jal/jalx to 26 bit target (shifted left 2)
    case IMAGE_REL_BASED_MIPS_JMPADDR16:
      if(debug_show) printf("fixup %08x -> ", *addr);
      
      value = *(WORD *)addr & 0x3ff;
      value = (value >> 5) | ((value & 0x1f) << 5);
      value = (value << 16) | *((WORD *)addr + 1);
      value += offset >> 2;      
      *((WORD *)addr + 1) = LOWORD(value);
      
      value = HIWORD(value) & 0x3ff;
      value = (value >> 5) | ((value & 0x1f) << 5);
      *(WORD *)addr = LOWORD((*(WORD *)addr & 0x1c00) | value);

      if(debug_show) printf("%08x", *addr);
      break;
    
    default:

⌨️ 快捷键说明

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