mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-08 19:04:45 +00:00
Bug 1547113: Add support for section table parsing to nt::PEHeaders; r=mhowell
Differential Revision: https://phabricator.services.mozilla.com/D28905 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
6e39f30075
commit
c2bb05fdfb
@ -17,6 +17,8 @@
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/LauncherResult.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Span.h"
|
||||
|
||||
// The declarations within this #if block are intended to be used for initial
|
||||
// process initialization ONLY. You probably don't want to be using these in
|
||||
@ -294,7 +296,7 @@ class MOZ_RAII PEHeaders final {
|
||||
* address of the binary.
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
T RVAToPtr(R aRva) {
|
||||
T RVAToPtr(R aRva) const {
|
||||
return RVAToPtr<T>(mMzHeader, aRva);
|
||||
}
|
||||
|
||||
@ -304,7 +306,7 @@ class MOZ_RAII PEHeaders final {
|
||||
* mapping.
|
||||
*/
|
||||
template <typename T, typename R>
|
||||
T RVAToPtr(void* aBase, R aRva) {
|
||||
T RVAToPtr(void* aBase, R aRva) const {
|
||||
if (!mImageLimit) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -477,6 +479,53 @@ class MOZ_RAII PEHeaders final {
|
||||
return RVAToPtr<T>(dataEntry->OffsetToData);
|
||||
}
|
||||
|
||||
template <size_t N>
|
||||
Maybe<Span<const uint8_t>> FindSection(const char (&aSecName)[N],
|
||||
DWORD aCharacteristicsMask) const {
|
||||
static_assert((N - 1) <= IMAGE_SIZEOF_SHORT_NAME,
|
||||
"Section names must be at most 8 characters excluding null "
|
||||
"terminator");
|
||||
|
||||
if (!(*this)) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
Span<IMAGE_SECTION_HEADER> sectionTable = GetSectionTable();
|
||||
for (auto&& sectionHeader : sectionTable) {
|
||||
if (strncmp(reinterpret_cast<const char*>(sectionHeader.Name), aSecName,
|
||||
IMAGE_SIZEOF_SHORT_NAME)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!(sectionHeader.Characteristics & aCharacteristicsMask)) {
|
||||
// We found the section but it does not have the expected
|
||||
// characteristics
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
DWORD rva = sectionHeader.VirtualAddress;
|
||||
if (!rva) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
DWORD size = sectionHeader.Misc.VirtualSize;
|
||||
if (!size) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
auto base = RVAToPtr<const uint8_t*>(rva);
|
||||
return Some(MakeSpan(base, size));
|
||||
}
|
||||
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
// There may be other code sections in the binary besides .text
|
||||
Maybe<Span<const uint8_t>> GetTextSectionInfo() const {
|
||||
return FindSection(".text", IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE |
|
||||
IMAGE_SCN_MEM_READ);
|
||||
}
|
||||
|
||||
static bool IsValid(PIMAGE_IMPORT_DESCRIPTOR aImpDesc) {
|
||||
return aImpDesc && aImpDesc->OriginalFirstThunk != 0;
|
||||
}
|
||||
@ -499,10 +548,20 @@ class MOZ_RAII PEHeaders final {
|
||||
// This private variant does not have bounds checks, because we need to be
|
||||
// able to resolve the bounds themselves.
|
||||
template <typename T, typename R>
|
||||
T RVAToPtrUnchecked(R aRva) {
|
||||
T RVAToPtrUnchecked(R aRva) const {
|
||||
return reinterpret_cast<T>(reinterpret_cast<char*>(mMzHeader) + aRva);
|
||||
}
|
||||
|
||||
Span<IMAGE_SECTION_HEADER> GetSectionTable() const {
|
||||
MOZ_ASSERT(*this);
|
||||
auto base = RVAToPtr<PIMAGE_SECTION_HEADER>(&mPeHeader->OptionalHeader,
|
||||
mPeHeader->FileHeader.SizeOfOptionalHeader);
|
||||
// The Windows loader has an internal limit of 96 sections (per PE spec)
|
||||
auto numSections = std::min(mPeHeader->FileHeader.NumberOfSections,
|
||||
WORD(96));
|
||||
return MakeSpan(base, numSections);
|
||||
}
|
||||
|
||||
PIMAGE_RESOURCE_DIRECTORY_ENTRY
|
||||
FindResourceEntry(PIMAGE_RESOURCE_DIRECTORY aCurLevel, WORD aId) {
|
||||
// Immediately after the IMAGE_RESOURCE_DIRECTORY structure is an array
|
||||
|
Loading…
Reference in New Issue
Block a user