コード例 #1
0
ファイル: symtab.c プロジェクト: yukke-fj/shamrock
static BOOL DLSYM_lookup_symtab(const char *sym_name, struct Elf32_Sym *symtab,
                                Elf32_Word symnum, Elf32_Addr *sym_value,
                                BOOL require_local_binding)
{
   Elf32_Addr sym_idx;

#if LOADER_DEBUG
      if (debugging_on)
         DLIF_trace("DLSYM_lookup_symtab, sym to find : %s\n", sym_name);
#endif

   for (sym_idx = 0; sym_idx < symnum; sym_idx++)
   {
#if LOADER_DEBUG
      if (debugging_on)
         DLIF_trace("\tPotential symbol match : %s\n", 
                 (char*)symtab[sym_idx].st_name);
#endif

      if ((symtab[sym_idx].st_shndx != SHN_UNDEF) && ((require_local_binding && 
          (ELF32_ST_BIND(symtab[sym_idx].st_info) == STB_LOCAL)) ||
  	  (!require_local_binding && 
	  (ELF32_ST_BIND(symtab[sym_idx].st_info) != STB_LOCAL))) &&
          !strcmp(sym_name,(char*)(symtab[sym_idx].st_name))) 
      {
         if (sym_value) *sym_value = symtab[sym_idx].st_value;
         return TRUE;
      }
   }
   if (sym_value) *sym_value = 0;
   return FALSE;
}
コード例 #2
0
ファイル: symtab.c プロジェクト: yukke-fj/shamrock
BOOL DLSYM_canonical_lookup(DLOAD_HANDLE handle, int sym_index, 
                            DLIMP_Dynamic_Module *dyn_module, 
                            Elf32_Addr *sym_value)
{
   /*------------------------------------------------------------------------*/
   /* Lookup the symbol table to get the symbol characteristics.             */
   /*------------------------------------------------------------------------*/
   struct Elf32_Sym *sym = &dyn_module->symtab[sym_index];
   int32_t           st_bind = ELF32_ST_BIND(sym->st_info);
   int32_t           st_vis  = ELF32_ST_VISIBILITY(sym->st_other);
   BOOL              is_def  = (sym->st_shndx != SHN_UNDEF && 
                               (sym->st_shndx < SHN_LORESERVE || 
                                sym->st_shndx == SHN_ABS || 
                                sym->st_shndx == SHN_COMMON || 
                                sym->st_shndx == SHN_XINDEX));
   const char *sym_name = (char *)sym->st_name; 

#if LOADER_DEBUG
   if (debugging_on)
      DLIF_trace("DLSYM_canonical_lookup: %d, %s\n", sym_index, sym_name);
#endif

   /*------------------------------------------------------------------------*/
   /* Local symbols and symbol definitions that cannot be pre-empted         */
   /* are resolved by the definition in the same module.                     */
   /*------------------------------------------------------------------------*/
   if (st_bind == STB_LOCAL || st_vis != STV_DEFAULT)
   {
      /*---------------------------------------------------------------------*/
      /* If it is a local symbol or non-local that cannot be preempted,      */
      /* the definition should be found in the same module. If we don't      */
      /* find the definition it is an error.                                 */
      /*---------------------------------------------------------------------*/
      if (!is_def)
      {
         DLIF_error(DLET_SYMBOL, 
                    "Local/non-imported symbol %s definition is not found "
                    "in module %s!\n", sym_name, dyn_module->name);
         return FALSE;
      }
      else
      {
         if (sym_value) *sym_value = sym->st_value;
         return TRUE; 
      }
   }
   /*------------------------------------------------------------------------*/
   /* Else we have either pre-emptable defintion or undef symbol. We need    */
   /* to do global look up.                                                  */
   /*------------------------------------------------------------------------*/
   else 
   {
      return DLSYM_global_lookup(handle, sym_name, dyn_module->loaded_module, 
                                 sym_value);
   }
}
コード例 #3
0
ファイル: symtab.c プロジェクト: Hashcode/ipcdev
void DLSYM_copy_globals(DLIMP_Dynamic_Module *dyn_module)
{
   Elf32_Word i, global_index, global_symnum;
   DLIMP_Loaded_Module *module = dyn_module->loaded_module;

#if LOADER_DEBUG
   if (debugging_on)
      DLIF_trace("DLSYM_copy_globals:\n");
#endif

   /*------------------------------------------------------------------------*/
   /* The dynamic symbol table is sorted so that the local symbols come      */
   /* before the global symbols. gsymtab_offset points to the address where   */
   /* the first global symbol starts. Only the global symbols need to be     */
   /* copied into the persistent info.                                       */
   /*------------------------------------------------------------------------*/
   global_index  = dyn_module->gsymtab_offset / sizeof(struct Elf32_Sym);
   global_symnum = dyn_module->symnum - global_index;

   /*------------------------------------------------------------------------*/
   /* Create space for the new global symbol table.                          */
   /*------------------------------------------------------------------------*/

   if (module->gsymtab)
       DLIF_free(module->gsymtab);
   module->gsymtab = DLIF_malloc(sizeof(struct Elf32_Sym) * global_symnum);
   module->gsymnum = global_symnum;

   if (module->gsymtab)
      memcpy(module->gsymtab,
             &dyn_module->symtab[global_index],
             sizeof(struct Elf32_Sym) * global_symnum);

   /*------------------------------------------------------------------------*/
   /* Copy the string table part that contains the global symbol names.      */
   /*------------------------------------------------------------------------*/
   if (module->gstrtab)
       DLIF_free(module->gstrtab);

   module->gstrsz  = dyn_module->strsz - dyn_module->gstrtab_offset;
   module->gstrtab = DLIF_malloc(module->gstrsz);

   if (module->gstrtab)
      memcpy(module->gstrtab,
             dyn_module->strtab + dyn_module->gstrtab_offset,
             module->gstrsz);

   /*------------------------------------------------------------------------*/
   /* Update the symbol names of the global symbol entries to point to       */
   /* the symbol names in the string table.                                  */
   /* NOTE: Note that we don't set the offset into the string table. We      */
   /* instead set the full address so that the st_name field can be accessed */
   /* as char *.                                                             */
   /*------------------------------------------------------------------------*/
   for (i = 0; i < global_symnum; i++)
   {

      Elf32_Word old_offset = dyn_module->symtab[i + global_index].st_name -
                              (Elf32_Addr) dyn_module->strtab;
      Elf32_Word new_offset = old_offset - dyn_module->gstrtab_offset;
      if(module->gsymtab) {
         struct Elf32_Sym *sym = &((struct Elf32_Sym*)(module->gsymtab))[i];
         sym->st_name = new_offset + (Elf32_Addr)module->gstrtab;
      }
#if LOADER_DEBUG
      if (debugging_on) DLIF_trace("Copying symbol: %s\n", (char *)
                                 dyn_module->symtab[i + global_index].st_name);
#endif
   }
}
コード例 #4
0
ファイル: symtab.c プロジェクト: Hashcode/ipcdev
BOOL DLSYM_global_lookup(DLOAD_HANDLE handle,
                         const char    *sym_name,
                         DLIMP_Loaded_Module *loaded_module,
                         Elf32_Addr    *sym_value)
{
   int i = 0;
   loaded_module_ptr_Queue_Node* node;
   LOADER_OBJECT *dHandle = (LOADER_OBJECT *)handle;

#if LOADER_DEBUG
   if (debugging_on)
      DLIF_trace("DLSYM_global_lookup: %s\n", sym_name);
#endif

   /*------------------------------------------------------------------------*/
   /* We will choose a different lookup algorithm based on what kind of      */
   /* platform we are supporting.  In the Braveheart case, the global symbol */
   /* lookup algorithm searches the base image first, followed by the        */
   /* explicit children of the specified Module.                             */
   /*------------------------------------------------------------------------*/
   if (loaded_module->direct_dependent_only)
   {
      int* child_handle = (int*)(loaded_module->dependencies.buf);

      /*---------------------------------------------------------------------*/
      /* Spin through list of this Module's dependencies (anything on its    */
      /* DT_NEEDED list), searching through each dependent's symbol table    */
      /* to find the symbol we are after.                                    */
      /*---------------------------------------------------------------------*/
      for (i = 0; i < loaded_module->dependencies.size; i++)
      {
         for (node = dHandle->DLIMP_loaded_objects.front_ptr;
           node->value->file_handle != child_handle[i];
           node=node->next_ptr);

         /*------------------------------------------------------------------*/
         /* Return true if we find the symbol.                               */
         /*------------------------------------------------------------------*/
         if (DLSYM_lookup_global_symtab(sym_name,
                                        node->value->gsymtab,
                                        node->value->gsymnum,
                                        sym_value))
            return TRUE;
      }
   }

   /*------------------------------------------------------------------------*/
   /* In the LINUX model, we will use a breadth-first global symbol lookup   */
   /* algorithm.  First, the application's global symbol table is searched,  */
   /* followed by its children, followed by their children, and so on.       */
   /* It is up to the client of this module to set the application handle.   */
   /*------------------------------------------------------------------------*/
   else
   {
      if (breadth_first_lookup(handle, sym_name, DLIMP_application_handle,
                               sym_value))
         return TRUE;
   }

   /*------------------------------------------------------------------------*/
   /* If we got this far, then symbol was not found.                         */
   /*------------------------------------------------------------------------*/
   DLIF_error(DLET_SYMBOL, "Could not resolve symbol %s!\n", sym_name);

   return FALSE;
}
コード例 #5
0
ファイル: c60_reloc.c プロジェクト: yukke-fj/shamrock
static void write_reloc_r(uint8_t* buffered_segment, 
                          uint32_t segment_offset,
                          int r_type, uint32_t r)
{
   uint32_t* rel_field_ptr = (uint32_t*)(buffered_segment + segment_offset);

#if LOADER_DEBUG
   /*------------------------------------------------------------------------*/
   /* Print some details about the relocation we are about to process.       */
   /*------------------------------------------------------------------------*/
   if(debugging_on)
   {
          DLIF_trace("RWRT: segment_offset: %d\n", segment_offset);
          DLIF_trace("RWRT: buffered_segment: 0x%x\n", 
	                                         (uint32_t)buffered_segment);
          DLIF_trace("RWRT: rel_field_ptr: 0x%x\n", (uint32_t)rel_field_ptr);
          DLIF_trace("RWRT: result: 0x%x\n", r);
   }
#endif


   /*------------------------------------------------------------------------*/
   /* Given the relocation type, carry out relocation into a 4 byte packet   */
   /* within the buffered segment.                                           */
   /*------------------------------------------------------------------------*/
   switch(r_type)
   {
      case R_C6000_ABS32:
          *rel_field_ptr = r;
          break;
      case R_C6000_PREL31:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(30,0)) | r;
          break;
      case R_C6000_ABS16:
          *((uint16_t*)(buffered_segment + segment_offset)) = r;
          break;
      case R_C6000_ABS8:
          *((uint8_t*)(buffered_segment + segment_offset)) = r;
          break;
     case R_C6000_PCR_S21:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(21,7)) | (r << 7);
          break;
      case R_C6000_PCR_S12:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(12,16)) | (r << 16);
          break;
      case R_C6000_PCR_S10:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(10,13)) | (r << 13);
          break;
      case R_C6000_PCR_S7:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(7,16)) | (r << 16);
          break;

      case R_C6000_ABS_S16:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(16,7)) | (r << 7);
          break;
      case R_C6000_ABS_L16:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(16,7)) | (r << 7);
          break;
      case R_C6000_ABS_H16:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(16,7)) | (r << 7);
          break;

      case R_C6000_SBR_U15_B:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(15,8)) | (r << 8);
          break;
      case R_C6000_SBR_U15_H:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(15,8)) | (r << 8);
          break;
      case R_C6000_SBR_U15_W:
      case R_C6000_DSBT_INDEX:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(15,8)) | (r << 8);
          break;

      case R_C6000_SBR_S16: 
      case R_C6000_SBR_L16_B: 
      case R_C6000_SBR_L16_H:
      case R_C6000_SBR_L16_W: 
      case R_C6000_SBR_H16_B: 
      case R_C6000_SBR_H16_H:
      case R_C6000_SBR_H16_W:
          *rel_field_ptr = (*rel_field_ptr & ~MASK(16,7)) | (r << 7);
          break;
          
      /*---------------------------------------------------------------------*/
      /* Linux "import-as-own" copy relocations are not yet supported.       */
      /*---------------------------------------------------------------------*/
      case R_C6000_COPY:

      default:
          DLIF_error(DLET_RELOC, 
                     "write_reloc_r called with invalid relocation type!\n");
  }

#if LOADER_DEBUG
  if (debugging_on)
     DLIF_trace("reloc_field 0x%x\n", *rel_field_ptr);
#endif
}
コード例 #6
0
ファイル: c60_reloc.c プロジェクト: yukke-fj/shamrock
static void reloc_do(C60_RELOC_TYPE r_type,
                     uint32_t segment_vaddr, 
                     uint8_t *segment_buffer, 
                     uint32_t addend, 
                     uint32_t symval,
                     uint32_t spc, 
                     int      wrong_endian,
                     uint32_t base_pointer,
                     int32_t  dsbt_index)
{
   int32_t reloc_value = 0;

#if LOADER_DEBUG || LOADER_PROFILE
   /*------------------------------------------------------------------------*/
   /* In debug mode, keep a count of the number of relocations processed.    */
   /* In profile mode, start the clock on a given relocation.                */
   /*------------------------------------------------------------------------*/
   int start_time = 0;
   if (debugging_on || profiling_on)
   {
      DLREL_relocations++;
      if (profiling_on) start_time = clock();
   }
#endif

   /*------------------------------------------------------------------------*/
   /* Calculate the relocation value according to the rules associated with  */
   /* the given relocation type.                                             */
   /*------------------------------------------------------------------------*/
   switch(r_type)
   {
      /*---------------------------------------------------------------------*/
      /* Straight-Up Address relocations (address references).               */
      /*---------------------------------------------------------------------*/
      case R_C6000_ABS32: 
      case R_C6000_ABS16: 
      case R_C6000_ABS8:
      case R_C6000_ABS_S16: 
      case R_C6000_ABS_L16: 
      case R_C6000_ABS_H16:
         reloc_value = symval + addend;
         break;

      /*---------------------------------------------------------------------*/
      /* PC-Relative relocations (calls and branches).                       */
      /*---------------------------------------------------------------------*/
      case R_C6000_PCR_S21: 
      case R_C6000_PCR_S12:
      case R_C6000_PCR_S10:
      case R_C6000_PCR_S7:
      {
         /*------------------------------------------------------------------*/
         /* Add SPC to segment address to get the PC. Mask for exec-packet   */
         /* boundary.                                                        */
         /*------------------------------------------------------------------*/
         int32_t opnd_p = (spc + segment_vaddr) & 0xffffffe0;
         reloc_value = symval + addend - opnd_p;
         break;
      }

      /*---------------------------------------------------------------------*/
      /* "Place"-relative relocations (TDEH).                                */
      /*---------------------------------------------------------------------*/
      /* These relocations occur in data and refer to a label that occurs    */
      /* at some signed 32-bit offset from the place where the relocation    */
      /* occurs.                                                             */
      /*---------------------------------------------------------------------*/
      case R_C6000_PREL31:
      {
         /*------------------------------------------------------------------*/
         /* Compute location of relocation entry and subtract it from the    */
         /* address of the location being referenced (it is computed very    */
         /* much like a PC-relative relocation, but it occurs in data and    */
         /* is called a "place"-relative relocation).                        */
         /*------------------------------------------------------------------*/
         /* If this is an Elf32_Rel type relocation, then addend is assumed  */
         /* to have been scaled when it was unpacked (field << 1).           */
         /*------------------------------------------------------------------*/
         /* For Elf32_Rela type relocations the addend is assumed to be a    */
         /* signed 32-bit integer value.                                     */
         /*------------------------------------------------------------------*/
         /* Offset is not fetch-packet relative; doesn't need to be masked.  */
         /*------------------------------------------------------------------*/
         int32_t opnd_p = (spc + segment_vaddr);
         reloc_value = symval + addend - opnd_p;
         break;
      }

      /*---------------------------------------------------------------------*/
      /* Static-Base Relative relocations (near-DP).                         */
      /*---------------------------------------------------------------------*/
      case R_C6000_SBR_U15_B: 
      case R_C6000_SBR_U15_H: 
      case R_C6000_SBR_U15_W:
      case R_C6000_SBR_S16:
      case R_C6000_SBR_L16_B:
      case R_C6000_SBR_L16_H:
      case R_C6000_SBR_L16_W:
      case R_C6000_SBR_H16_B:
      case R_C6000_SBR_H16_H: 
      case R_C6000_SBR_H16_W:
         reloc_value = symval + addend - base_pointer;
         break;

      /*---------------------------------------------------------------------*/
      /* R_C6000_DSBT_INDEX - uses value assigned by the dynamic loader to   */
      /*    be the DSBT index for this module as a scaled offset when        */
      /*    referencing the DSBT. The DSBT base address is in symval and the */
      /*    static base is in base_pointer. DP-relative offset to slot in    */
      /*    DSBT is the offset of the DSBT relative to the DP plus the       */
      /*    scaled DSBT index into the DSBT.                                 */
      /*---------------------------------------------------------------------*/
      case R_C6000_DSBT_INDEX:
         reloc_value = ((symval + addend) - base_pointer) + (dsbt_index << 2);
         break;

      /*---------------------------------------------------------------------*/
      /* Linux "import-as-own" copy relocation: after DSO initialization,    */
      /* copy the named object from the DSO into the executable's BSS        */
      /*---------------------------------------------------------------------*/
      /* Linux "import-as-own" copy relocations are not yet supported.       */
      /*---------------------------------------------------------------------*/
      case R_C6000_COPY:

      /*---------------------------------------------------------------------*/
      /* Unrecognized relocation type.                                       */
      /*---------------------------------------------------------------------*/
      default: 
         DLIF_error(DLET_RELOC, 
                    "reloc_do called with invalid relocation type!\n");
         break;
   }

   /*------------------------------------------------------------------------*/
   /* Overflow checking.  Is relocation value out of range for the size and  */
   /* type of the current relocation?                                        */
   /*------------------------------------------------------------------------*/
   if (rel_overflow(r_type, reloc_value))
      DLIF_error(DLET_RELOC, "relocation overflow!\n");

   /*------------------------------------------------------------------------*/
   /* Move relocation value to appropriate offset for relocation field's     */
   /* location.                                                              */
   /*------------------------------------------------------------------------*/
   reloc_value = pack_result(reloc_value, r_type);

   /*------------------------------------------------------------------------*/
   /* Mask packed result to the size of the relocation field.                */
   /*------------------------------------------------------------------------*/
   reloc_value = mask_result(reloc_value, r_type);

   /*------------------------------------------------------------------------*/
   /* If necessary, Swap endianness of data at relocation address.           */
   /*------------------------------------------------------------------------*/
   if (wrong_endian)
      DLIMP_change_endian32((int32_t*)(segment_buffer + spc));

   /*------------------------------------------------------------------------*/
   /* Write the relocated 4-byte packet back to the segment buffer.          */
   /*------------------------------------------------------------------------*/
   write_reloc_r(segment_buffer, spc, r_type, reloc_value);

   /*------------------------------------------------------------------------*/
   /* Change endianness of segment address back to original.                 */
   /*------------------------------------------------------------------------*/
   if (wrong_endian)
      DLIMP_change_endian32((int32_t*)(segment_buffer + spc));

#if LOADER_DEBUG || LOADER_PROFILE
   /*------------------------------------------------------------------------*/
   /* In profile mode, add elapsed time for this relocation to total time    */
   /* spent doing relocations.                                               */
   /*------------------------------------------------------------------------*/
   if (profiling_on)
      DLREL_total_reloc_time += (clock() - start_time);
   if (debugging_on)
      DLIF_trace("reloc_value = 0x%x\n", reloc_value);
#endif
}