/** * Returns the value of the specified 64 bits general purpose register * */ DISDECL(int) DISFetchReg64(PCCPUMCTXCORE pCtx, unsigned reg64, uint64_t *pVal) { AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *pVal = 0, VERR_INVALID_PARAMETER); *pVal = DIS_READ_REG64(pCtx, reg64); return VINF_SUCCESS; }
/** * Returns the pointer to the specified 64 bits general purpose register */ DISDECL(int) DISPtrReg64(PCPUMCTXCORE pCtx, unsigned reg64, uint64_t **ppReg) { AssertReturnStmt(reg64 < RT_ELEMENTS(g_aReg64Index), *ppReg = NULL, VERR_INVALID_PARAMETER); *ppReg = DIS_PTR_REG64(pCtx, reg64); return VINF_SUCCESS; }
RTDECL(ssize_t) RTLinuxFindDevicePathV(dev_t DevNum, RTFMODE fMode, char *pszBuf, size_t cchBuf, const char *pszSuggestion, va_list va) { AssertReturnStmt(cchBuf >= 2, errno = EINVAL, -1); AssertReturnStmt( fMode == RTFS_TYPE_DEV_CHAR || fMode == RTFS_TYPE_DEV_BLOCK, errno = EINVAL, -1); if (pszSuggestion) { /* * Construct the filename and read the link. */ char szFilename[RTPATH_MAX]; int rc = rtLinuxConstructPathV(szFilename, sizeof(szFilename), "/dev/", pszSuggestion, va); if (rc == -1) return -1; /* * Check whether the caller's suggestion was right. */ RTFSOBJINFO Info; rc = RTPathQueryInfo(szFilename, &Info, RTFSOBJATTRADD_UNIX); if ( RT_SUCCESS(rc) && Info.Attr.u.Unix.Device == DevNum && (Info.Attr.fMode & RTFS_TYPE_MASK) == fMode) { size_t cchPath = strlen(szFilename); if (cchPath >= cchBuf) { errno = EOVERFLOW; return -1; } memcpy(pszBuf, szFilename, cchPath + 1); return cchPath; } /* The suggestion was wrong, fall back on the brute force attack. */ } return rtLinuxFindDevicePathRecursive(DevNum, fMode, "/dev/", pszBuf, cchBuf); }
/** Allocate (and return) a buffer for a device list in VRDP wire format, * and populate from a PUSBDEVICE linked list. @a pLen takes the length of * the new list. * See @a Console::processRemoteUSBDevices for the receiving end. */ static void *buildWireListFromDevices(PUSBDEVICE pDevices, int *pLen) { char *pBuf; unsigned cDevs, cbBuf, iCurrent; uint16_t iNext; PUSBDEVICE pCurrent; cDevs = countUSBDevices(pDevices); cbBuf = cDevs * DEV_ENTRY_SIZE + 2; pBuf = (char *)xmalloc(cbBuf); memset(pBuf, 0, cbBuf); for (pCurrent = pDevices, iCurrent = 0; pCurrent; pCurrent = pCurrent->pNext, iCurrent += iNext, --cDevs) { unsigned i, cZeros; AssertReturnStmt(iCurrent + DEV_ENTRY_SIZE + 2 <= cbBuf, free(pBuf), NULL); fillWireListEntry(pBuf + iCurrent, pCurrent, &iNext); DevListEntry *pEntry = (DevListEntry *)(pBuf + iCurrent); /* Sanity tests */ for (i = iCurrent + sizeof(DevListEntry), cZeros = 0; i < iCurrent + iNext; ++i) if (pBuf[i] == 0) ++cZeros; AssertReturnStmt(cZeros == RT_BOOL(pEntry->oManufacturer) + RT_BOOL(pEntry->oProduct) + RT_BOOL(pEntry->oSerialNumber), free(pBuf), NULL); Assert(pEntry->oManufacturer == 0 || pBuf[iCurrent + pEntry->oManufacturer] != '\0'); Assert(pEntry->oProduct == 0 || pBuf[iCurrent + pEntry->oProduct] != '\0'); Assert(pEntry->oSerialNumber == 0 || pBuf[iCurrent + pEntry->oSerialNumber] != '\0'); AssertReturnStmt(cZeros == 0 || pBuf[iCurrent + iNext - 1] == '\0', free(pBuf), NULL); } *pLen = iCurrent + iNext + 2; Assert(cDevs == 0); Assert(*pLen <= cbBuf); return pBuf; }
/** * Constructs the path of a sysfs file from the format parameters passed, * prepending a prefix if the path is relative. * * @returns The number of characters returned, or -1 and errno set to ERANGE on * failure. * * @param pszPrefix The prefix to prepend if the path is relative. Must end * in '/'. * @param pszBuf Where to write the path. Must be at least * sizeof(@a pszPrefix) characters long * @param cchBuf The size of the buffer pointed to by @a pszBuf. * @param pszFormat The name format, either absolute or relative to the * prefix specified by @a pszPrefix. * @param va The format args. */ static ssize_t rtLinuxConstructPathV(char *pszBuf, size_t cchBuf, const char *pszPrefix, const char *pszFormat, va_list va) { size_t cchPrefix = strlen(pszPrefix); AssertReturnStmt(pszPrefix[cchPrefix - 1] == '/', errno = ERANGE, -1); AssertReturnStmt(cchBuf > cchPrefix + 1, errno = ERANGE, -1); /** @todo While RTStrPrintfV prevents overflows, it doesn't make it easy to * check for truncations. RTPath should provide some formatters and * joiners which can take over this rather common task that is * performed here. */ size_t cch = RTStrPrintfV(pszBuf, cchBuf, pszFormat, va); if (*pszBuf != '/') { AssertReturnStmt(cchBuf >= cch + cchPrefix + 1, errno = ERANGE, -1); memmove(pszBuf + cchPrefix, pszBuf, cch + 1); memcpy(pszBuf, pszPrefix, cchPrefix); cch += cchPrefix; } return cch; }
RTDECL(ssize_t) RTLinuxSysFsGetLinkDestV(char *pszBuf, size_t cchBuf, const char *pszFormat, va_list va) { AssertReturnStmt(cchBuf >= 2, errno = EINVAL, -1); /* * Construct the filename and read the link. */ char szFilename[RTPATH_MAX]; int rc = rtLinuxSysFsConstructPath(szFilename, sizeof(szFilename), pszFormat, va); if (rc == -1) return -1; char szLink[RTPATH_MAX]; rc = readlink(szFilename, szLink, sizeof(szLink)); if (rc == -1) return -1; if ((size_t)rc > sizeof(szLink) - 1) { errno = ERANGE; return -1; } szLink[rc] = '\0'; /* readlink fun. */ /* * Extract the file name component and copy it into the return buffer. */ size_t cchName; const char *pszName = RTPathFilename(szLink); if (pszName) { cchName = strlen(pszName); /* = &szLink[rc] - pszName; */ if (cchName >= cchBuf) { errno = ERANGE; return -1; } memcpy(pszBuf, pszName, cchName + 1); } else { *pszBuf = '\0'; cchName = 0; } return cchName; }
/** * Add an entry for an I/O stream using a passthru stream. * * The passthru I/O stream will hash all the data read from or written to the * stream and automatically add an entry to the manifest with the desired * attributes when it is released. Alternatively one can call * RTManifestPtIosAddEntryNow() to have more control over exactly when this * action is performed and which status it yields. * * @returns IPRT status code. * @param hManifest The manifest to add the entry to. * @param hVfsIos The I/O stream to pass thru to/from. * @param pszEntry The entry name. * @param fAttrs The attributes to create for this stream. * @param fReadOrWrite Whether it's a read or write I/O stream. * @param phVfsIosPassthru Where to return the new handle. */ RTDECL(int) RTManifestEntryAddPassthruIoStream(RTMANIFEST hManifest, RTVFSIOSTREAM hVfsIos, const char *pszEntry, uint32_t fAttrs, bool fReadOrWrite, PRTVFSIOSTREAM phVfsIosPassthru) { /* * Validate input. */ AssertReturn(fAttrs < RTMANIFEST_ATTR_END, VERR_INVALID_PARAMETER); AssertPtr(pszEntry); AssertPtr(phVfsIosPassthru); uint32_t cRefs = RTManifestRetain(hManifest); AssertReturn(cRefs != UINT32_MAX, VERR_INVALID_HANDLE); cRefs = RTVfsIoStrmRetain(hVfsIos); AssertReturnStmt(cRefs != UINT32_MAX, RTManifestRelease(hManifest), VERR_INVALID_HANDLE); /* * Create an instace of the passthru I/O stream. */ PRTMANIFESTPTIOS pThis; RTVFSIOSTREAM hVfsPtIos; int rc = RTVfsNewIoStream(&g_rtManifestPassthruIosOps, sizeof(*pThis), fReadOrWrite ? RTFILE_O_READ : RTFILE_O_WRITE, NIL_RTVFS, NIL_RTVFSLOCK, &hVfsPtIos, (void **)&pThis); if (RT_SUCCESS(rc)) { pThis->hVfsIos = hVfsIos; pThis->pHashes = rtManifestHashesCreate(fAttrs); pThis->hManifest = hManifest; pThis->fReadOrWrite = fReadOrWrite; pThis->fAddedEntry = false; pThis->pszEntry = RTStrDup(pszEntry); if (pThis->pszEntry && pThis->pHashes) { *phVfsIosPassthru = hVfsPtIos; return VINF_SUCCESS; } RTVfsIoStrmRelease(hVfsPtIos); } else { RTVfsIoStrmRelease(hVfsIos); RTManifestRelease(hManifest); } return rc; }
/** * Does the deferred loading of the real data (image and/or debug info). * * @returns VINF_SUCCESS or VERR_DBG_DEFERRED_LOAD_FAILED. * @param pMod The generic module instance data. * @param fForcedRetry Whether it's a forced retry by one of the * pfnTryOpen methods. */ static int rtDbgModDeferredDoIt(PRTDBGMODINT pMod, bool fForcedRetry) { RTCritSectEnter(&pMod->CritSect); int rc; if (!pMod->fDeferredFailed || fForcedRetry) { bool const fDbgVt = pMod->pDbgVt == &g_rtDbgModVtDbgDeferred; bool const fImgVt = pMod->pImgVt == &g_rtDbgModVtImgDeferred; AssertReturnStmt(fDbgVt || fImgVt, RTCritSectLeave(&pMod->CritSect), VERR_INTERNAL_ERROR_5); PRTDBGMODDEFERRED pThis = (PRTDBGMODDEFERRED)(fDbgVt ? pMod->pvDbgPriv : pMod->pvImgPriv); /* Reset the method tables and private data pointes so the deferred loading procedure can figure out what to do and won't get confused. */ if (fDbgVt) { pMod->pvDbgPriv = NULL; pMod->pDbgVt = NULL; } if (fImgVt) { pMod->pvImgPriv = NULL; pMod->pImgVt = NULL; } /* Do the deferred loading. */ rc = pThis->pfnDeferred(pMod, pThis); if (RT_SUCCESS(rc)) { Assert(!fDbgVt || pMod->pDbgVt != NULL); Assert(!fImgVt || pMod->pImgVt != NULL); pMod->fDeferred = false; pMod->fDeferredFailed = false; rtDbgModDeferredReleaseInstanceData(pThis); if (fImgVt && fDbgVt) rtDbgModDeferredReleaseInstanceData(pThis); } else { /* Failed, bail out and restore the deferred setup. */ pMod->fDeferredFailed = true; if (fDbgVt) { Assert(!pMod->pDbgVt); pMod->pDbgVt = &g_rtDbgModVtDbgDeferred; pMod->pvDbgPriv = pThis; } if (fImgVt) { Assert(!pMod->pImgVt); pMod->pImgVt = &g_rtDbgModVtImgDeferred; pMod->pvImgPriv = pThis; } } } else rc = VERR_DBG_DEFERRED_LOAD_FAILED; RTCritSectLeave(&pMod->CritSect); return rc; }
/** * Returns the value of the specified segment register including a pointer to the hidden register in the supplied cpu context * */ DISDECL(int) DISFetchRegSegEx(PCPUMCTXCORE pCtx, DISSELREG sel, PCPUMSELREG *ppSelReg) { AssertReturnStmt((unsigned)sel < RT_ELEMENTS(g_aRegSegIndex), *ppSelReg = NULL, VERR_INVALID_PARAMETER); *ppSelReg = (CPUMSELREG *)((uintptr_t)pCtx + g_aRegHidSegIndex[sel]); return VINF_SUCCESS; }
static ssize_t rtLinuxFindDevicePathRecursive(dev_t DevNum, RTFMODE fMode, const char *pszBasePath, char *pszBuf, size_t cchBuf) { /* * Check assumptions made by the code below. */ size_t const cchBasePath = strlen(pszBasePath); AssertReturnStmt(cchBasePath < RTPATH_MAX - 10U, errno = ENAMETOOLONG, -1); ssize_t rcRet; PRTDIR pDir; int rc = RTDirOpen(&pDir, pszBasePath); if (RT_SUCCESS(rc)) { char szPath[RTPATH_MAX]; /** @todo 4K per recursion - can easily be optimized away by passing it along pszBasePath and only remember the length. */ memcpy(szPath, pszBasePath, cchBasePath + 1); for (;;) { RTDIRENTRYEX Entry; rc = RTDirReadEx(pDir, &Entry, NULL, RTFSOBJATTRADD_UNIX, RTPATH_F_ON_LINK); if (RT_FAILURE(rc)) { errno = rc == VERR_NO_MORE_FILES ? ENOENT : rc == VERR_BUFFER_OVERFLOW ? EOVERFLOW : EIO; rcRet = -1; break; } if (RTFS_IS_SYMLINK(Entry.Info.Attr.fMode)) continue; /* Do the matching. */ if ( Entry.Info.Attr.u.Unix.Device == DevNum && (Entry.Info.Attr.fMode & RTFS_TYPE_MASK) == fMode) { rcRet = rtLinuxConstructPath(pszBuf, cchBuf, pszBasePath, "%s", Entry.szName); break; } /* Recurse into subdirectories. */ if (!RTFS_IS_DIRECTORY(Entry.Info.Attr.fMode)) continue; if (Entry.szName[0] == '.') continue; szPath[cchBasePath] = '\0'; rc = RTPathAppend(szPath, sizeof(szPath) - 1, Entry.szName); /* -1: for slash */ if (RT_FAILURE(rc)) { errno = ENAMETOOLONG; rcRet = -1; break; } strcat(&szPath[cchBasePath], "/"); rcRet = rtLinuxFindDevicePathRecursive(DevNum, fMode, szPath, pszBuf, cchBuf); if (rcRet >= 0 || errno != ENOENT) break; } RTDirClose(pDir); } else { rcRet = -1; errno = RTErrConvertToErrno(rc); } return rcRet; }