Changeset 34177 in vbox for trunk/src/VBox/Additions
- Timestamp:
- Nov 18, 2010 3:12:24 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 67904
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/crOpenGL/fakedri_drv.c
r33540 r34177 82 82 #else 83 83 # define DRI_ELFSYM Elf32_Sym 84 #endif 85 86 #ifdef RT_ARCH_AMD64 87 typedef struct _FAKEDRI_PatchNode 88 { 89 const char* psFuncName; 90 void *pDstStart, *pDstEnd; 91 const void *pSrcStart, *pSrcEnd; 92 93 struct _FAKEDRI_PatchNode *pNext; 94 } FAKEDRI_PatchNode; 95 static FAKEDRI_PatchNode *g_pFreeList=NULL, *g_pRepatchList=NULL; 84 96 #endif 85 97 … … 129 141 130 142 static void 143 vboxApplyPatch(const char* psFuncName, void *pDst, const void *pSrc, unsigned long size) 144 { 145 void *alPatch; 146 int rv; 147 148 /* Get aligned start address we're going to patch*/ 149 alPatch = (void*) ((uintptr_t)pDst & ~(uintptr_t)(PAGESIZE-1)); 150 151 #ifndef VBOX_NO_MESA_PATCH_REPORTS 152 crDebug("MProtecting: %p, %li", alPatch, pDst-alPatch+size); 153 #endif 154 155 /* Get write access to mesa functions */ 156 rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_WRITE|RTMEM_PROT_EXEC); 157 if (RT_FAILURE(rv)) 158 { 159 crError("mprotect failed with %x (%s)", rv, psFuncName); 160 } 161 162 #ifndef VBOX_NO_MESA_PATCH_REPORTS 163 crDebug("Writing %li bytes to %p from %p", size, pDst, pSrc); 164 #endif 165 166 crMemcpy(pDst, pSrc, size); 167 168 /*@todo Restore the protection, probably have to check what was it before us...*/ 169 rv = RTMemProtect(alPatch, pDst-alPatch+size, RTMEM_PROT_READ|RTMEM_PROT_EXEC); 170 if (RT_FAILURE(rv)) 171 { 172 crError("mprotect2 failed with %x (%s)", rv, psFuncName); 173 } 174 } 175 176 static void 131 177 vboxPatchMesaExport(const char* psFuncName, const void *pStart, const void *pEnd) 132 178 { … … 172 218 173 219 pEnd = pStart + sym1->st_size; 220 # ifndef VBOX_NO_MESA_PATCH_REPORTS 221 crDebug("VBox Entry: %p, start: %p(%s:%s), size: %li", pStart, dlip1.dli_saddr, dlip1.dli_fname, dlip1.dli_sname, sym1->st_size); 222 # endif 223 } 224 #endif 225 174 226 #ifndef VBOX_NO_MESA_PATCH_REPORTS 175 crDebug("VBox Entry: %p, start: %p(%s:%s), size: %i", pStart, dlip1.dli_saddr, dlip1.dli_fname, dlip1.dli_sname, sym1->st_size); 176 #endif 177 } 178 #endif 179 180 #ifndef VBOX_NO_MESA_PATCH_REPORTS 181 crDebug("Mesa Entry: %p, start: %p(%s:%s), size: %i", pMesaEntry, dlip.dli_saddr, dlip.dli_fname, dlip.dli_sname, sym->st_size); 182 crDebug("Vbox code: start: %p, end %p, size: %i", pStart, pEnd, pEnd-pStart); 227 crDebug("Mesa Entry: %p, start: %p(%s:%s), size: %li", pMesaEntry, dlip.dli_saddr, dlip.dli_fname, dlip.dli_sname, sym->st_size); 228 crDebug("Vbox code: start: %p, end %p, size: %li", pStart, pEnd, pEnd-pStart); 183 229 #endif 184 230 … … 189 235 /* Try to insert 5 bytes jmp/jmpq to our stub code */ 190 236 191 if (5>(pEnd-pStart)) 192 { 193 crDebug("Can't patch size too small.(%s)", psFuncName); 237 if (sym->st_size<5) 238 { 239 if (crStrcmp(psFuncName, "glXCreateGLXPixmapMESA")) 240 { 241 crError("Can't patch size too small.(%s)", psFuncName); 242 } 194 243 return; 195 244 } 196 245 197 246 shift = (void*)((intptr_t)pStart-((intptr_t)dlip.dli_saddr+5)); 198 # 247 #ifndef VBOX_NO_MESA_PATCH_REPORTS 199 248 crDebug("Inserting jmp[q] with shift %p instead", shift); 200 # 249 #endif 201 250 202 251 #ifdef RT_ARCH_AMD64 … … 206 255 if (offset>INT32_MAX || offset<INT32_MIN) 207 256 { 208 crDebug("Can't patch offset is too big.(%s)", psFuncName); 257 FAKEDRI_PatchNode *pNode; 258 # ifndef VBOX_NO_MESA_PATCH_REPORTS 259 crDebug("Can't patch offset is too big. Pushing for 2nd pass(%s)", psFuncName); 260 # endif 261 /*Add patch node to repatch with chain jmps in 2nd pass*/ 262 pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode)); 263 if (!pNode) 264 { 265 crError("Not enough memory."); 266 return; 267 } 268 pNode->psFuncName = psFuncName; 269 pNode->pDstStart = dlip.dli_saddr; 270 pNode->pDstEnd = dlip.dli_saddr+sym->st_size; 271 pNode->pSrcStart = pStart; 272 pNode->pSrcEnd = pEnd; 273 pNode->pNext = g_pRepatchList; 274 g_pRepatchList = pNode; 209 275 return; 210 276 } … … 213 279 214 280 patch[0] = 0xE9; 215 patch[1] = ((char*)&shift)[0]; 216 patch[2] = ((char*)&shift)[1]; 217 patch[3] = ((char*)&shift)[2]; 218 patch[4] = ((char*)&shift)[3]; 219 220 # ifndef VBOX_NO_MESA_PATCH_REPORTS 281 crMemcpy(&patch[1], &shift, 4); 282 #ifndef VBOX_NO_MESA_PATCH_REPORTS 221 283 crDebug("Patch: E9 %x", *((int*)&patch[1])); 222 # 284 #endif 223 285 pStart = &patch[0]; 224 286 pEnd = &patch[5]; 225 287 } 226 288 227 /* Get aligned start address we're going to patch*/ 228 alPatch = (void*) ((uintptr_t)dlip.dli_saddr & ~(uintptr_t)(PAGESIZE-1)); 229 230 #ifndef VBOX_NO_MESA_PATCH_REPORTS 231 crDebug("MProtecting: %p, %i", alPatch, dlip.dli_saddr-alPatch+pEnd-pStart); 232 #endif 233 234 /* Get write access to mesa functions */ 235 rv = RTMemProtect(alPatch, dlip.dli_saddr-alPatch+pEnd-pStart, 236 RTMEM_PROT_READ|RTMEM_PROT_WRITE|RTMEM_PROT_EXEC); 237 if (RT_FAILURE(rv)) 238 { 239 crError("mprotect failed with %x (%s)", rv, psFuncName); 240 } 241 242 #ifndef VBOX_NO_MESA_PATCH_REPORTS 243 crDebug("Writing %i bytes to %p from %p", pEnd-pStart, dlip.dli_saddr, pStart); 244 #endif 245 246 crMemcpy(dlip.dli_saddr, pStart, pEnd-pStart); 247 248 /*@todo Restore the protection, probably have to check what was it before us...*/ 249 rv = RTMemProtect(alPatch, dlip.dli_saddr-alPatch+pEnd-pStart, 250 RTMEM_PROT_READ|RTMEM_PROT_EXEC); 251 if (RT_FAILURE(rv)) 252 { 253 crError("mprotect2 failed with %x (%s)", rv, psFuncName); 254 } 255 } 289 vboxApplyPatch(psFuncName, dlip.dli_saddr, pStart, pEnd-pStart); 290 291 #ifdef RT_ARCH_AMD64 292 /*Add rest of mesa function body to free list*/ 293 if (sym->st_size-(pEnd-pStart)>=5) 294 { 295 FAKEDRI_PatchNode *pNode = (FAKEDRI_PatchNode *)crAlloc(sizeof(FAKEDRI_PatchNode)); 296 if (pNode) 297 { 298 pNode->psFuncName = psFuncName; 299 pNode->pDstStart = dlip.dli_saddr+(pEnd-pStart); 300 pNode->pDstEnd = dlip.dli_saddr+sym->st_size; 301 pNode->pSrcStart = dlip.dli_saddr; 302 pNode->pSrcEnd = NULL; 303 pNode->pNext = g_pFreeList; 304 g_pFreeList = pNode; 305 } 306 } 307 #endif 308 } 309 310 #ifdef RT_ARCH_AMD64 311 static void 312 vboxRepatchMesaExports(void) 313 { 314 FAKEDRI_PatchNode *pFreeNode, *pPatchNode; 315 int64_t offset; 316 char patch[12]; 317 318 pPatchNode = g_pRepatchList; 319 while (pPatchNode) 320 { 321 # ifndef VBOX_NO_MESA_PATCH_REPORTS 322 crDebug("\nvboxRepatchMesaExports %s", pPatchNode->psFuncName); 323 # endif 324 /*find free place in mesa functions, to place 64bit jump to our stub code*/ 325 pFreeNode = g_pFreeList; 326 while (pFreeNode) 327 { 328 if (pFreeNode->pDstEnd-pFreeNode->pDstStart>=12) 329 { 330 offset = ((intptr_t)pFreeNode->pDstStart-((intptr_t)pPatchNode->pDstStart+5)); 331 if (offset<=INT32_MAX && offset>=INT32_MIN) 332 { 333 break; 334 } 335 } 336 pFreeNode=pFreeNode->pNext; 337 } 338 339 if (!pFreeNode) 340 { 341 crError("Failed to find free space, to place repatch for %s.", pPatchNode->psFuncName); 342 return; 343 } 344 345 /*add 32bit rel jmp, from mesa orginal function to free space in other mesa function*/ 346 patch[0] = 0xE9; 347 crMemcpy(&patch[1], &offset, 4); 348 # ifndef VBOX_NO_MESA_PATCH_REPORTS 349 crDebug("Adding jmp from mesa %s to mesa %s+%#lx", pPatchNode->psFuncName, pFreeNode->psFuncName, 350 pFreeNode->pDstStart-pFreeNode->pSrcStart); 351 # endif 352 vboxApplyPatch(pPatchNode->psFuncName, pPatchNode->pDstStart, &patch[0], 5); 353 354 /*add 64bit abs jmp, from free space to our stub code*/ 355 patch[0] = 0x48; /*movq %rax,imm64*/ 356 patch[1] = 0xB8; 357 crMemcpy(&patch[2], &pPatchNode->pSrcStart, 8); 358 patch[10] = 0xFF; /*jmp *%rax*/ 359 patch[11] = 0xE0; 360 # ifndef VBOX_NO_MESA_PATCH_REPORTS 361 crDebug("Adding jmp from mesa %s+%#lx to vbox %s", pFreeNode->psFuncName, pFreeNode->pDstStart-pFreeNode->pSrcStart, 362 pPatchNode->psFuncName); 363 # endif 364 vboxApplyPatch(pFreeNode->psFuncName, pFreeNode->pDstStart, &patch[0], 12); 365 /*mark this space as used*/ 366 pFreeNode->pDstStart = pFreeNode->pDstStart+12; 367 368 pPatchNode = pPatchNode->pNext; 369 } 370 } 371 372 static void 373 vboxFakeDriFreeList(FAKEDRI_PatchNode *pList) 374 { 375 FAKEDRI_PatchNode *pNode; 376 377 while (pList) 378 { 379 pNode=pList; 380 pList=pNode->pNext; 381 crFree(pNode); 382 } 383 } 384 #endif 256 385 257 386 #ifdef VBOX_OGL_GLX_USE_CSTUBS … … 267 396 crDebug("Patching mesa glx entries"); 268 397 #include "fakedri_glxfuncsList.h" 398 399 #ifdef RT_ARCH_AMD64 400 vboxRepatchMesaExports(); 401 vboxFakeDriFreeList(g_pRepatchList); 402 g_pRepatchList = NULL; 403 vboxFakeDriFreeList(g_pFreeList); 404 g_pFreeList = NULL; 405 #endif 269 406 } 270 407 #undef GLXAPI_ENTRY
Note:
See TracChangeset
for help on using the changeset viewer.