Exemplo n.º 1
0
static bool getSymbolInfo(ShHandle compiler, ANGLEShaderSymbolType symbolType, Vector<ANGLEShaderSymbol>& symbols)
{
    switch (symbolType) {
    case SHADER_SYMBOL_TYPE_UNIFORM: {
        auto uniforms = ShGetUniforms(compiler);
        if (!uniforms)
            return false;
        for (const auto& uniform : *uniforms)
            getSymbolInfo(uniform, symbolType, symbols);
        break;
    }
    case SHADER_SYMBOL_TYPE_VARYING: {
        auto varyings = ShGetVaryings(compiler);
        if (!varyings)
            return false;
        for (const auto& varying : *varyings)
            getSymbolInfo(varying, symbolType, symbols);
        break;
    }
    case SHADER_SYMBOL_TYPE_ATTRIBUTE: {
        auto attributes = ShGetAttributes(compiler);
        if (!attributes)
            return false;
        for (const auto& attribute : *attributes)
            getSymbolInfo(attribute, symbolType, symbols);
        break;
    }
    default:
        ASSERT_NOT_REACHED();
        return false;
    }
    return true;
}
Exemplo n.º 2
0
bool ANGLEPlatformBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions)
{
    if (!builtCompilers) {
        m_fragmentCompiler = ShConstructCompiler(SH_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
        m_vertexCompiler = ShConstructCompiler(SH_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
        if (!m_fragmentCompiler || !m_vertexCompiler) {
            cleanupCompilers();
            return false;
        }

        builtCompilers = true;
    }

    ShHandle compiler;

    if (shaderType == SHADER_TYPE_VERTEX)
        compiler = m_vertexCompiler;
    else
        compiler = m_fragmentCompiler;

    const char* const shaderSourceStrings[] = { shaderSource };

#if ANGLE_SH_VERSION >= 111
    bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions);
#else
    bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_ATTRIBUTES_UNIFORMS | extraCompileOptions);
#endif
    if (!validateSuccess) {
        int logSize = getValidationResultValue(compiler, SH_INFO_LOG_LENGTH);
        if (logSize > 1) {
            OwnPtr<char[]> logBuffer = adoptArrayPtr(new char[logSize]);
            if (logBuffer) {
                ShGetInfoLog(compiler, logBuffer.get());
                shaderValidationLog = logBuffer.get();
            }
        }
        return false;
    }

    int translationLength = getValidationResultValue(compiler, SH_OBJECT_CODE_LENGTH);
    if (translationLength > 1) {
        OwnPtr<char[]> translationBuffer = adoptArrayPtr(new char[translationLength]);
        if (!translationBuffer)
            return false;
        ShGetObjectCode(compiler, translationBuffer.get());
        translatedShaderSource = translationBuffer.get();
    }

    if (!getSymbolInfo(compiler, SH_ACTIVE_ATTRIBUTES, symbols))
        return false;
    if (!getSymbolInfo(compiler, SH_ACTIVE_UNIFORMS, symbols))
        return false;

    return true;
}
Exemplo n.º 3
0
bool ANGLEWebKitBridge::compileShaderSource(const char* shaderSource, ANGLEShaderType shaderType, String& translatedShaderSource, String& shaderValidationLog, Vector<ANGLEShaderSymbol>& symbols, int extraCompileOptions)
{
    if (!builtCompilers) {
        m_fragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
        m_vertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, m_shaderSpec, m_shaderOutput, &m_resources);
        if (!m_fragmentCompiler || !m_vertexCompiler) {
            cleanupCompilers();
            return false;
        }

        builtCompilers = true;
    }
    
    ShHandle compiler;

    if (shaderType == SHADER_TYPE_VERTEX)
        compiler = m_vertexCompiler;
    else
        compiler = m_fragmentCompiler;

    const char* const shaderSourceStrings[] = { shaderSource };

    bool validateSuccess = ShCompile(compiler, shaderSourceStrings, 1, SH_OBJECT_CODE | SH_VARIABLES | extraCompileOptions);
    if (!validateSuccess) {
        const std::string& log = ShGetInfoLog(compiler);
        if (log.length())
            shaderValidationLog = log.c_str();
        return false;
    }

    const std::string& objectCode = ShGetObjectCode(compiler);
    if (objectCode.length())
        translatedShaderSource = objectCode.c_str();
    
    if (!getSymbolInfo(compiler, SHADER_SYMBOL_TYPE_ATTRIBUTE, symbols))
        return false;
    if (!getSymbolInfo(compiler, SHADER_SYMBOL_TYPE_UNIFORM, symbols))
        return false;
    if (!getSymbolInfo(compiler, SHADER_SYMBOL_TYPE_VARYING, symbols))
        return false;

    return true;
}
Exemplo n.º 4
0
bool process::loadDYNINSTlib() {
  /* Look for a function we can hijack to forcibly load dyninstapi_rt. 
     This is effectively an inferior RPC with the caveat that we're
     overwriting code instead of allocating memory from the RT heap. 
     (So 'hijack' doesn't mean quite what you might think.) */
  Address codeBase = findFunctionToHijack(this);	

  if( !codeBase ) { return false; }
  
  /* glibc 2.3.4 and higher adds a fourth parameter to _dl_open().
     While we could probably get away with treating the three and four
     -argument functions the same, check the version anyway, since
     we'll probably need to later. */
  bool useFourArguments = true;
  Symbol libcVersionSymbol;
  if( getSymbolInfo( "__libc_version", libcVersionSymbol ) ) {
    char libcVersion[ sizeof( int ) * libcVersionSymbol.size() + 1 ];
	libcVersion[ sizeof( int ) * libcVersionSymbol.size() ] = '\0';
    if( ! readDataSpace( (void *) libcVersionSymbol.addr(), libcVersionSymbol.size(), libcVersion, true ) ) {
      fprintf( stderr, "%s[%d]: warning, failed to read libc version, assuming 2.3.4+\n", __FILE__, __LINE__ );
      }
    else {
      startup_printf( "%s[%d]: libcVersion: %s\n", __FILE__, __LINE__, libcVersion );

      /* We could potentially add a sanity check here to make sure we're looking at 2.3.x. */
      int microVersion = ((int)libcVersion[4]) - ((int)'0');
      if( microVersion <= 3 ) {
	    useFourArguments = false;
        }
      } /* end if we read the version symbol */
    } /* end if we found the version symbol */

  if( useFourArguments ) { startup_printf( "%s[%d]: using four arguments.\n", __FILE__, __LINE__ ); }

  /* Fetch the name of the run-time library. */
  const char DyninstEnvVar[]="DYNINSTAPI_RT_LIB";
        
  if( ! dyninstRT_name.length() ) { // we didn't get anything on the command line
    if (getenv(DyninstEnvVar) != NULL) {
      dyninstRT_name = getenv(DyninstEnvVar);
    } else {
      pdstring msg = pdstring( "Environment variable " + pdstring( DyninstEnvVar )
			       + " has not been defined for process " ) + pdstring( getPid() );
      showErrorCallback(101, msg);
      return false;
    } /* end if enviromental variable not found */
  } /* end enviromental variable extraction */
        
  /* Save the (main thread's) current PC.*/
  savedPC = getRepresentativeLWP()->getActiveFrame().getPC();	
        
  /* _dl_open() takes three arguments: a pointer to the library name,
     the DLOPEN_MODE, and the return address of the current frame
     (that is, the location of the SIGILL-generating bundle we'll use
     to handleIfDueToDyninstLib()).  We construct the first here. */
        
  /* Write the string to entry, and then move the PC to the next bundle. */
  codeGen gen(BYTES_TO_SAVE);
        
  Address dyninstlib_addr = gen.used() + codeBase;
  gen.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
        
  Address dlopencall_addr = gen.used() + codeBase;
	
  /* At this point, we use the generic iRPC headers and trailers
     around the call to _dl_open.  (Note that pre-1.35 versions
     of this file had a simpler mechanism well-suited to boot-
     strapping a new port.  The current complexity is to handle
     the attach() case, where we don't know if execution was stopped
     at the entry the entry point to a function. */

  bool ok = theRpcMgr->emitInferiorRPCheader(gen);
  if( ! ok ) { return false; }
	
  /* Generate the call to _dl_open with a large dummy constant as the
     the third argument to make sure we generate the same size code the second
     time around, with the correct "return address." (dyninstlib_brk_addr) */
  // As a quick note, we want to "return" to the beginning of the restore
  // segment, not dyninstlib_brk_addr (or we skip all the restores).
  // Of course, we're not sure what this addr represents....

  pdvector< AstNode * > dlOpenArguments( 4 );
  AstNode * dlOpenCall;
	
  dlOpenArguments[ 0 ] = new AstNode( AstNode::Constant, (void *)dyninstlib_addr );
  dlOpenArguments[ 1 ] = new AstNode( AstNode::Constant, (void *)DLOPEN_MODE );
  dlOpenArguments[ 2 ] = new AstNode( AstNode::Constant, (void *)0xFFFFFFFFFFFFFFFF );
  if( useFourArguments ) { 
  	/* I derived the -2 as follows: from dlfcn/dlopen.c in the glibc sources, line 59,
  	   we find the call to _dl_open(), whose last argument is 'args->file == NULL ? LM_ID_BASE : NS'.
  	   Since the filename we pass in is non-null, this means we (would) pass in NS, which
  	   is defined to be __LM_ID_CALLER in the same file, line 48.  (Since glibc must be shared
  	   for us to be calling _dl_open(), we fall into the second case of the #ifdef.)  __LM_ID_CALLER
  	   is defined in include/dlfcn.h, where it has the value -2. */
    dlOpenArguments[ 3 ] = new AstNode( AstNode::Constant, (void *)(long unsigned int)-2 );
    }
  dlOpenCall = new AstNode( "_dl_open", dlOpenArguments );
	
  /* Remember where we originally generated the call. */
  codeBufIndex_t index = gen.getIndex();
	
  /* emitInferiorRPCheader() configures (the global) registerSpace for us. */
  dlOpenCall->generateCode( this, regSpace, gen, true, true );

  // Okay, we're done with the generation, and we know where we'll be.
  // Go back and regenerate it
  Address dlopenRet = codeBase + gen.used();
  gen.setIndex(index);

  /* Clean up the reference counts before regenerating. */
  removeAst( dlOpenCall );
  removeAst( dlOpenArguments[ 2 ] );
	
  dlOpenArguments[ 2 ] = new AstNode( AstNode::Constant, (void *)dlopenRet );
  dlOpenCall = new AstNode( "_dl_open", dlOpenArguments );
	
  /* Regenerate the call at the same original location with the correct constants. */
  dlOpenCall->generateCode( this, regSpace, gen, true, true );

  /* Clean up the reference counting. */
  removeAst( dlOpenCall );
  removeAst( dlOpenArguments[ 0 ] );
  removeAst( dlOpenArguments[ 1 ] );
  removeAst( dlOpenArguments[ 2 ] );
  if( useFourArguments ) { removeAst( dlOpenArguments[ 3 ] ); }

  // Okay, that was fun. Now restore. And trap. And stuff.
        
	
  unsigned breakOffset, resultOffset, justAfterResultOffset;
  ok = theRpcMgr->emitInferiorRPCtrailer(gen, breakOffset, false, 
					 resultOffset, justAfterResultOffset );
  if( ! ok ) { return false; }					 

  /* Let everyone else know that we're expecting a SIGILL. */
  dyninstlib_brk_addr = codeBase + breakOffset;

  assert(gen.used() < BYTES_TO_SAVE);

  /* Save the function we're going to hijack. */
  InsnAddr iAddr = InsnAddr::generateFromAlignedDataAddress( codeBase, this );
  /* We need to save the whole buffer, because we don't know how big gen is
     when we do the restore.  This could be made more efficient by storing
     gen.used() somewhere. */
  iAddr.saveBundlesTo( savedCodeBuffer, sizeof( savedCodeBuffer ) / 16 );

  /* Write the call into the mutatee. */
  InsnAddr jAddr = InsnAddr::generateFromAlignedDataAddress( codeBase, this );
  jAddr.writeBundlesFrom( (unsigned char *)gen.start_ptr(), gen.used() / 16 );

  /* Now that we know where the code will start, move the (main thread's) PC there. */
  getRepresentativeLWP()->changePC( dlopencall_addr, NULL );

  /* Let them know we're working on it. */
  setBootstrapState( loadingRT_bs );
  return true;
} /* end dlopenDYNINSTlib() */