Top


定義場所(file name)

hotspot/src/os/linux/vm/os_linux.cpp

説明(description)

  // Loads .dll/.so and
  // in case of error it checks if .dll/.so was built for the
  // same architecture as Hotspot is running on

名前(function name)

void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
{

本体部(body)

  {- -------------------------------------------
  (1) ::dlopen() が成功すればそれを返す.
      ---------------------------------------- -}

      void * result= ::dlopen(filename, RTLD_LAZY);
      if (result != NULL) {
        // Successful loading
        return result;
      }

  {- -------------------------------------------
  (1) (以下は ::dlopen() が失敗した場合の処理.
       失敗の原因を少し調べて分かりやすいエラーメッセージを返すようにしている.)
      ---------------------------------------- -}

      Elf32_Ehdr elf_head;

      // Read system error message into ebuf
      // It may or may not be overwritten below
      ::strncpy(ebuf, ::dlerror(), ebuflen-1);
      ebuf[ebuflen-1]='\0';
      int diag_msg_max_length=ebuflen-strlen(ebuf);
      char* diag_msg_buf=ebuf+strlen(ebuf);

      if (diag_msg_max_length==0) {
        // No more space in ebuf for additional diagnostics message
        return NULL;
      }


    {- -------------------------------------------
  (1.1) (ELF ファイルのヘッダ部分を取得する)
        ---------------------------------------- -}

      int file_descriptor= ::open(filename, O_RDONLY | O_NONBLOCK);

      if (file_descriptor < 0) {
        // Can't open library, report dlerror() message
        return NULL;
      }

      bool failed_to_read_elf_head=
        (sizeof(elf_head)!=
            (::read(file_descriptor, &elf_head,sizeof(elf_head)))) ;

      ::close(file_descriptor);
      if (failed_to_read_elf_head) {
        // file i/o error - report dlerror() msg
        return NULL;
      }

    {- -------------------------------------------
  (1.1) (以下は調査用の型/定数の宣言)
        ---------------------------------------- -}

      typedef struct {
        Elf32_Half  code;         // Actual value as defined in elf.h
        Elf32_Half  compat_class; // Compatibility of archs at VM's sense
        char        elf_class;    // 32 or 64 bit
        char        endianess;    // MSB or LSB
        char*       name;         // String representation
      } arch_t;

      #ifndef EM_486
      #define EM_486          6               /* Intel 80486 */
      #endif

      static const arch_t arch_array[]={
        {EM_386,         EM_386,     ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
        {EM_486,         EM_386,     ELFCLASS32, ELFDATA2LSB, (char*)"IA 32"},
        {EM_IA_64,       EM_IA_64,   ELFCLASS64, ELFDATA2LSB, (char*)"IA 64"},
        {EM_X86_64,      EM_X86_64,  ELFCLASS64, ELFDATA2LSB, (char*)"AMD 64"},
        {EM_SPARC,       EM_SPARC,   ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
        {EM_SPARC32PLUS, EM_SPARC,   ELFCLASS32, ELFDATA2MSB, (char*)"Sparc 32"},
        {EM_SPARCV9,     EM_SPARCV9, ELFCLASS64, ELFDATA2MSB, (char*)"Sparc v9 64"},
        {EM_PPC,         EM_PPC,     ELFCLASS32, ELFDATA2MSB, (char*)"Power PC 32"},
        {EM_PPC64,       EM_PPC64,   ELFCLASS64, ELFDATA2MSB, (char*)"Power PC 64"},
        {EM_ARM,         EM_ARM,     ELFCLASS32,   ELFDATA2LSB, (char*)"ARM"},
        {EM_S390,        EM_S390,    ELFCLASSNONE, ELFDATA2MSB, (char*)"IBM System/390"},
        {EM_ALPHA,       EM_ALPHA,   ELFCLASS64, ELFDATA2LSB, (char*)"Alpha"},
        {EM_MIPS_RS3_LE, EM_MIPS_RS3_LE, ELFCLASS32, ELFDATA2LSB, (char*)"MIPSel"},
        {EM_MIPS,        EM_MIPS,    ELFCLASS32, ELFDATA2MSB, (char*)"MIPS"},
        {EM_PARISC,      EM_PARISC,  ELFCLASS32, ELFDATA2MSB, (char*)"PARISC"},
        {EM_68K,         EM_68K,     ELFCLASS32, ELFDATA2MSB, (char*)"M68k"}
      };

      #if  (defined IA32)
        static  Elf32_Half running_arch_code=EM_386;
      #elif   (defined AMD64)
        static  Elf32_Half running_arch_code=EM_X86_64;
      #elif  (defined IA64)
        static  Elf32_Half running_arch_code=EM_IA_64;
      #elif  (defined __sparc) && (defined _LP64)
        static  Elf32_Half running_arch_code=EM_SPARCV9;
      #elif  (defined __sparc) && (!defined _LP64)
        static  Elf32_Half running_arch_code=EM_SPARC;
      #elif  (defined __powerpc64__)
        static  Elf32_Half running_arch_code=EM_PPC64;
      #elif  (defined __powerpc__)
        static  Elf32_Half running_arch_code=EM_PPC;
      #elif  (defined ARM)
        static  Elf32_Half running_arch_code=EM_ARM;
      #elif  (defined S390)
        static  Elf32_Half running_arch_code=EM_S390;
      #elif  (defined ALPHA)
        static  Elf32_Half running_arch_code=EM_ALPHA;
      #elif  (defined MIPSEL)
        static  Elf32_Half running_arch_code=EM_MIPS_RS3_LE;
      #elif  (defined PARISC)
        static  Elf32_Half running_arch_code=EM_PARISC;
      #elif  (defined MIPS)
        static  Elf32_Half running_arch_code=EM_MIPS;
      #elif  (defined M68K)
        static  Elf32_Half running_arch_code=EM_68K;
      #else
        #error Method os::dll_load requires that one of following is defined:\
             IA32, AMD64, IA64, __sparc, __powerpc__, ARM, S390, ALPHA, MIPS, MIPSEL, PARISC, M68K
      #endif

    {- -------------------------------------------
  (1.1) (ELF ファイルのヘッダ部を調査する)
        ---------------------------------------- -}

      // Identify compatability class for VM's architecture and library's architecture
      // Obtain string descriptions for architectures

      arch_t lib_arch={elf_head.e_machine,0,elf_head.e_ident[EI_CLASS], elf_head.e_ident[EI_DATA], NULL};
      int running_arch_index=-1;

      for (unsigned int i=0 ; i < ARRAY_SIZE(arch_array) ; i++ ) {
        if (running_arch_code == arch_array[i].code) {
          running_arch_index    = i;
        }
        if (lib_arch.code == arch_array[i].code) {
          lib_arch.compat_class = arch_array[i].compat_class;
          lib_arch.name         = arch_array[i].name;
        }
      }

      assert(running_arch_index != -1,
        "Didn't find running architecture code (running_arch_code) in arch_array");

    {- -------------------------------------------
  (1.1) (分からなかった場合は dlerror() が返すエラーメッセージをそのまま使う)
        ---------------------------------------- -}

      if (running_arch_index == -1) {
        // Even though running architecture detection failed
        // we may still continue with reporting dlerror() message
        return NULL;
      }

    {- -------------------------------------------
  (1.1) (endiann が異なる場合)
        ---------------------------------------- -}

      if (lib_arch.endianess != arch_array[running_arch_index].endianess) {
        ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: endianness mismatch)");
        return NULL;
      }

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

    #ifndef S390
      if (lib_arch.elf_class != arch_array[running_arch_index].elf_class) {
        ::snprintf(diag_msg_buf, diag_msg_max_length-1," (Possible cause: architecture word width mismatch)");
        return NULL;
      }
    #endif // !S390

  {- -------------------------------------------
  (1) 
      ---------------------------------------- -}

      if (lib_arch.compat_class != arch_array[running_arch_index].compat_class) {
        if ( lib_arch.name!=NULL ) {
          ::snprintf(diag_msg_buf, diag_msg_max_length-1,
            " (Possible cause: can't load %s-bit .so on a %s-bit platform)",
            lib_arch.name, arch_array[running_arch_index].name);
        } else {
          ::snprintf(diag_msg_buf, diag_msg_max_length-1,
          " (Possible cause: can't load this .so (machine code=0x%x) on a %s-bit platform)",
            lib_arch.code,
            arch_array[running_arch_index].name);
        }
      }

      return NULL;
    }

This document is available under the GNU GENERAL PUBLIC LICENSE Version 2.