Changeset 75163 in vbox for trunk/src/VBox/Runtime/common/ldr
- Timestamp:
- Oct 29, 2018 8:58:56 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 126241
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/ldr/ldrLX.cpp
r74664 r75163 45 45 46 46 #include <iprt/formats/lx.h> 47 #include <iprt/formats/pecoff.h> 48 #include <iprt/formats/codeview.h> 49 #include <iprt/formats/elf32.h> 47 50 #include "internal/ldr.h" 48 51 … … 220 223 return RTErrInfoSetF(pErrInfo, VERR_LDRLX_BAD_LOADER_SECTION, 221 224 "Object table spans beyond the executable: e32_objcnt=%u", Hdr.e32_objcnt); 225 if (Hdr.e32_objcnt >= _32K) 226 return RTErrInfoSetF(pErrInfo, VERR_LDRLX_BAD_LOADER_SECTION, "Too many segments: %#x\n", Hdr.e32_objcnt); 222 227 if ( Hdr.e32_objmap 223 228 && (Hdr.e32_objmap < off || Hdr.e32_objmap > offEnd)) … … 267 272 */ 268 273 size_t cbModLXAndSegments = RT_ALIGN_Z(RT_UOFFSETOF_DYN(KLDRMODLX, aSegments[Hdr.e32_objcnt + 1]), 8); 274 cbModLXAndSegments += sizeof("segXXXXX") * (Hdr.e32_objcnt + 1); 275 269 276 pModLX = (PKLDRMODLX)RTMemAlloc(cbModLXAndSegments + Hdr.e32_ldrsize + 2 /*for two extra zeros*/); 270 277 if (!pModLX) … … 410 417 * object alignment. The linker typically uses 64KB alignment, 411 418 * we can easily get away with page alignment in most cases. 412 */ 413 fCanOptimizeMapping = !(Hdr.e32_mflags & (E32NOINTFIX | E32SYSDLL)); 419 * 420 * However, this screws up DwARF debug info, let's not do this 421 * when the purpose is reading debug info. 422 */ 423 /** @todo Add flag for enabling this optimization. */ 424 fCanOptimizeMapping = !(Hdr.e32_mflags & (E32NOINTFIX | E32SYSDLL)) 425 && !(fFlags & (RTLDR_O_FOR_DEBUG | RTLDR_O_FOR_VALIDATION)); 414 426 NextRVA = 0; 415 427 … … 417 429 * Setup the KLDRMOD segment array. 418 430 */ 431 char *pszSegNm = (char *)&pModLX->aSegments[pModLX->cSegments]; 419 432 for (i = 0; i < pModLX->cSegments; i++) 420 433 { 434 /* dummy segment name */ 435 pModLX->aSegments[i].pszName = pszSegNm; 436 size_t cchName = RTStrPrintf(pszSegNm, sizeof("segXXXXX"), "seg%u", i); 437 pszSegNm += cchName + 1; 438 pModLX->aSegments[i].cchName = (uint32_t)cchName; 439 421 440 /* unused */ 422 pModLX->aSegments[i].pszName = NULL;423 441 pModLX->aSegments[i].offFile = -1; 424 442 pModLX->aSegments[i].cbFile = -1; … … 449 467 else 450 468 pModLX->aSegments[i].cbMapped = pModLX->paObjs[i + 1].o32_base - pModLX->paObjs[i].o32_base; 469 /** @todo Above probably doesn't work for os2krnl and other images 470 * non-sequential virtual address assignments. */ 451 471 NextRVA += (uint32_t)pModLX->aSegments[i].cbMapped; 452 472 … … 1258 1278 #endif 1259 1279 1280 /** Helper for rtldrLX_EnumDbgInfo. */ 1281 static int rtldrLx_EnumDbgInfoHelper(PKLDRMODLX pModLX, PFNRTLDRENUMDBG pfnCallback, void *pvUser, 1282 uint8_t *pbBuf, uint32_t cbRead, uint32_t offDbgInfo, bool *pfReturn) 1283 { 1284 RTLDRDBGINFO DbgInfo; 1285 uint32_t iDbgInfo = 0; 1286 uint32_t cbDbgInfo = pModLX->Hdr.e32_debuglen; 1287 1288 /* 1289 * Recent watcom linkers emit PE style IMAGE_DEBUG_MISC for specifying 1290 * external file with CV info. 1291 */ 1292 if (cbRead >= sizeof(IMAGE_DEBUG_MISC)) 1293 { 1294 PCIMAGE_DEBUG_MISC pMisc = (PCIMAGE_DEBUG_MISC)pbBuf; 1295 if ( pMisc->DataType == IMAGE_DEBUG_MISC_EXENAME 1296 && pMisc->Length <= cbRead 1297 && pMisc->Length >= RT_UOFFSETOF(IMAGE_DEBUG_MISC, Data[4]) 1298 && pMisc->Unicode == 0 1299 && pMisc->Reserved[0] == 0 1300 && pMisc->Reserved[1] == 0 1301 && pMisc->Reserved[2] == 0 1302 && pMisc->Data[0] >= 0x20 1303 && pMisc->Data[0] < 0x7f 1304 && pMisc->Data[1] >= 0x20 1305 && pMisc->Data[1] < 0x7f 1306 && pMisc->Data[2] >= 0x20 1307 && pMisc->Data[2] < 0x7f ) 1308 { 1309 uint32_t cchMaxName = pMisc->Length - RT_UOFFSETOF(IMAGE_DEBUG_MISC, Data[0]); 1310 for (uint32_t cchName = 3; cchName < cchMaxName; cchName++) 1311 { 1312 char const ch = pMisc->Data[cchName]; 1313 if (ch == 0) 1314 { 1315 DbgInfo.enmType = RTLDRDBGINFOTYPE_CODEVIEW; 1316 DbgInfo.iDbgInfo = iDbgInfo; 1317 DbgInfo.offFile = offDbgInfo; 1318 DbgInfo.LinkAddress = NIL_RTLDRADDR; 1319 DbgInfo.cb = pMisc->Length; 1320 DbgInfo.pszExtFile = (char *)&pMisc->Data[0]; 1321 DbgInfo.u.Cv.cbImage = pModLX->Hdr.e32_mpages * pModLX->Hdr.e32_pagesize; 1322 DbgInfo.u.Cv.uTimestamp = 0; 1323 DbgInfo.u.Cv.uMajorVer = 0; 1324 DbgInfo.u.Cv.uMinorVer = 0; 1325 1326 *pfReturn = true; 1327 int rc = pfnCallback(&pModLX->Core, &DbgInfo, pvUser); 1328 if (rc != VINF_SUCCESS) 1329 return rc; 1330 } 1331 else if (ch >= 0x30 && ch < 0x7f) 1332 continue; 1333 break; 1334 } 1335 1336 /* Skip it. */ 1337 pbBuf += pMisc->Length; 1338 cbRead -= pMisc->Length; 1339 offDbgInfo += pMisc->Length; 1340 cbDbgInfo -= pMisc->Length; 1341 iDbgInfo++; 1342 } 1343 } 1344 1345 /* 1346 * Look for codeview signature. 1347 */ 1348 RTCVHDR const *pCvHdr = (RTCVHDR const *)pbBuf; 1349 if ( cbRead > sizeof(*pCvHdr) 1350 && pCvHdr->off >= sizeof(*pCvHdr) 1351 && pCvHdr->off < cbDbgInfo) 1352 { 1353 switch (pCvHdr->u32Magic) 1354 { 1355 case RTCVHDR_MAGIC_NB11: 1356 case RTCVHDR_MAGIC_NB09: 1357 case RTCVHDR_MAGIC_NB08: 1358 case RTCVHDR_MAGIC_NB07: 1359 case RTCVHDR_MAGIC_NB06: 1360 case RTCVHDR_MAGIC_NB05: 1361 case RTCVHDR_MAGIC_NB04: 1362 case RTCVHDR_MAGIC_NB02: 1363 case RTCVHDR_MAGIC_NB01: 1364 case RTCVHDR_MAGIC_NB00: 1365 DbgInfo.enmType = RTLDRDBGINFOTYPE_CODEVIEW; 1366 DbgInfo.iDbgInfo = iDbgInfo; 1367 DbgInfo.offFile = offDbgInfo; 1368 DbgInfo.LinkAddress = NIL_RTLDRADDR; 1369 DbgInfo.cb = cbDbgInfo; 1370 DbgInfo.pszExtFile = NULL; 1371 DbgInfo.u.Cv.cbImage = pModLX->Hdr.e32_mpages * pModLX->Hdr.e32_pagesize; 1372 DbgInfo.u.Cv.uTimestamp = 0; 1373 DbgInfo.u.Cv.uMajorVer = 0; 1374 DbgInfo.u.Cv.uMinorVer = 0; 1375 1376 *pfReturn = true; 1377 return pfnCallback(&pModLX->Core, &DbgInfo, pvUser); 1378 } 1379 } 1380 1381 /* 1382 * Watcom wraps its DWARF output in an ELF image, so look for and ELF magic. 1383 */ 1384 Elf32_Ehdr const *pElfHdr = (Elf32_Ehdr const *)pbBuf; 1385 if ( cbRead >= sizeof(*pElfHdr) 1386 && pElfHdr->e_ident[EI_MAG0] == ELFMAG0 1387 && pElfHdr->e_ident[EI_MAG1] == ELFMAG1 1388 && pElfHdr->e_ident[EI_MAG2] == ELFMAG2 1389 && pElfHdr->e_ident[EI_MAG3] == ELFMAG3 1390 && pElfHdr->e_ident[EI_CLASS] == ELFCLASS32 1391 && pElfHdr->e_ident[EI_DATA] == ELFDATA2LSB 1392 && pElfHdr->e_ident[EI_VERSION] == EV_CURRENT 1393 && pElfHdr->e_shentsize == sizeof(Elf32_Shdr) 1394 && pElfHdr->e_shnum >= 2 1395 && pElfHdr->e_shnum < _32K + 10 1396 && pElfHdr->e_shstrndx <= pElfHdr->e_shnum 1397 && pElfHdr->e_shstrndx > 0 1398 ) 1399 { 1400 /** @todo try use pBuf for reading into and try to read more at once. */ 1401 uint32_t const offShdrs = pElfHdr->e_shoff + offDbgInfo; 1402 uint32_t const cShdrs = pElfHdr->e_shnum; 1403 uint32_t const cbShdr = pElfHdr->e_shentsize; 1404 int rc = VINF_SUCCESS; 1405 1406 /* Read the section string table. */ 1407 Elf32_Shdr Shdr; 1408 int rc2 = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &Shdr, sizeof(Shdr), 1409 offShdrs + pElfHdr->e_shstrndx * cbShdr); 1410 if ( RT_SUCCESS(rc2) 1411 && Shdr.sh_offset > 0 1412 && Shdr.sh_size > 0 1413 && Shdr.sh_size < _256K 1414 && Shdr.sh_type == SHT_STRTAB) 1415 { 1416 uint32_t const cbStrTab = Shdr.sh_size; 1417 char * const pszStrTab = (char *)RTMemTmpAlloc(cbStrTab + 2); 1418 if (pszStrTab) 1419 { 1420 rc2 = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, pszStrTab, Shdr.sh_size, offDbgInfo + Shdr.sh_offset); 1421 if (RT_SUCCESS(rc2)) 1422 { 1423 pszStrTab[cbStrTab] = '\0'; 1424 1425 /* Iterate the sections, one by one. */ 1426 for (uint32_t i = 1; i < cShdrs; i++) 1427 { 1428 rc = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &Shdr, sizeof(Shdr), offShdrs + i * cbShdr); 1429 if ( RT_SUCCESS(rc) 1430 && Shdr.sh_name < cbStrTab 1431 && strncmp(&pszStrTab[Shdr.sh_name], RT_STR_TUPLE(".debug_")) == 0) 1432 { 1433 DbgInfo.enmType = RTLDRDBGINFOTYPE_DWARF; 1434 DbgInfo.iDbgInfo = iDbgInfo; 1435 DbgInfo.offFile = offDbgInfo + Shdr.sh_offset; 1436 DbgInfo.LinkAddress = NIL_RTLDRADDR; 1437 DbgInfo.cb = Shdr.sh_size; 1438 DbgInfo.pszExtFile = NULL; 1439 DbgInfo.u.Dwarf.pszSection = &pszStrTab[Shdr.sh_name]; 1440 1441 *pfReturn = true; 1442 rc = pfnCallback(&pModLX->Core, &DbgInfo, pvUser); 1443 if (rc != VINF_SUCCESS) 1444 break; 1445 iDbgInfo++; 1446 } 1447 } 1448 } 1449 RTMemTmpFree(pszStrTab); 1450 } 1451 } 1452 return rc; 1453 } 1454 1455 /* 1456 * Watcom debug info? Don't know how to detect it... 1457 */ 1458 1459 return VINF_SUCCESS; 1460 } 1461 1260 1462 1261 1463 /** … … 1274 1476 if (kldrModLXHasDbgInfo(pMod, pvBits)) 1275 1477 return VINF_SUCCESS; 1276 #if 0 1478 PKLDRMODLX pModLX = RT_FROM_MEMBER(pMod, KLDRMODLX, Core); 1479 1277 1480 /* 1278 1481 * Read the debug info and look for familiar magics and structures. 1279 1482 */ 1280 /** @todo */ 1281 #endif 1282 1283 return VINF_SUCCESS; 1483 union 1484 { 1485 uint8_t ab[1024]; 1486 IMAGE_DEBUG_MISC Misc; 1487 RTCVHDR CvHdr; 1488 } uBuf; 1489 1490 bool fReturn = false; 1491 1492 /* Try the offset without header displacement first. */ 1493 uint32_t cbToRead = RT_MIN(pModLX->Hdr.e32_debuglen, sizeof(uBuf)); 1494 int rc = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &uBuf, cbToRead, pModLX->Hdr.e32_debuginfo); 1495 if (RT_SUCCESS(rc)) 1496 rc = rtldrLx_EnumDbgInfoHelper(pModLX, pfnCallback, pvUser, &uBuf.ab[0], cbToRead, pModLX->Hdr.e32_debuginfo, &fReturn); 1497 1498 /* If that didn't yield anything, try displaying it by the header offset. */ 1499 if (!fReturn && pModLX->offHdr > 0) 1500 { 1501 rc = pModLX->Core.pReader->pfnRead(pModLX->Core.pReader, &uBuf, cbToRead, pModLX->Hdr.e32_debuginfo + pModLX->offHdr); 1502 if (RT_SUCCESS(rc)) 1503 rc = rtldrLx_EnumDbgInfoHelper(pModLX, pfnCallback, pvUser, &uBuf.ab[0], cbToRead, 1504 pModLX->Hdr.e32_debuginfo + pModLX->offHdr, &fReturn); 1505 } 1506 return rc; 1284 1507 } 1285 1508 … … 1291 1514 1292 1515 /* 1293 * Don't curre tnly bother with linkers which doesn't advertise it in the header.1516 * Don't currently bother with linkers which doesn't advertise it in the header. 1294 1517 */ 1295 1518 if ( !pModLX->Hdr.e32_debuginfo … … 2753 2976 { 2754 2977 PKLDRMODLX pThis = RT_FROM_MEMBER(pMod, KLDRMODLX, Core); 2755 if (iDbgInfo == 0) 2756 return pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvBuf, cb, off); 2757 return VERR_OUT_OF_RANGE; 2978 RT_NOREF(iDbgInfo); 2979 return pThis->Core.pReader->pfnRead(pThis->Core.pReader, pvBuf, cb, off); 2758 2980 } 2759 2981
Note:
See TracChangeset
for help on using the changeset viewer.