mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-08-14 01:54:07 +02:00
Update breakpad to make it work with MinGW
This commit is contained in:
490
thirdparty/breakpad/common/pecoff/pecoffutils.cc
vendored
Normal file
490
thirdparty/breakpad/common/pecoff/pecoffutils.cc
vendored
Normal file
@@ -0,0 +1,490 @@
|
||||
// Copyright (c) 2014 Google Inc.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are
|
||||
// met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above
|
||||
// copyright notice, this list of conditions and the following disclaimer
|
||||
// in the documentation and/or other materials provided with the
|
||||
// distribution.
|
||||
// * Neither the name of Google Inc. nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
// pecoffutils.c: Utilities for dealing with PECOFF files
|
||||
//
|
||||
|
||||
#include "common/pecoff/pecoffutils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <arpa/inet.h>
|
||||
#endif
|
||||
|
||||
namespace google_breakpad {
|
||||
|
||||
bool IsValidPeCoff(const uint8_t* obj_base) {
|
||||
// at offset 0x3c, find the offset to PE signature
|
||||
const uint32_t* peOffsetPtr = reinterpret_cast<const uint32_t*>(obj_base +
|
||||
IMAGE_FILE_HEADER_OFFSET);
|
||||
|
||||
// TODO: ideally we want to check that the offset is less than the size of the
|
||||
// mapped file, but we don't have that information at the moment
|
||||
//
|
||||
// if (*peOffsetPtr > size) return FALSE;
|
||||
|
||||
// check PE signature
|
||||
const PeHeader* peHeader = reinterpret_cast<const PeHeader*>(obj_base+*peOffsetPtr);
|
||||
if (peHeader->mMagic != IMAGE_FILE_MAGIC)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int PeCoffClass(const uint8_t* obj_base) {
|
||||
const uint32_t* peOffsetPtr = reinterpret_cast<const uint32_t*>(obj_base +
|
||||
IMAGE_FILE_HEADER_OFFSET);
|
||||
const PeHeader* peHeader = reinterpret_cast<const PeHeader*>(obj_base+*peOffsetPtr);
|
||||
const uint16_t* peOptionalHeader = reinterpret_cast<const uint16_t*>
|
||||
(reinterpret_cast<const uint8_t*>(peHeader) + sizeof(PeHeader));
|
||||
|
||||
// We need to read the magic before we know if this a Pe32OptionalHeader or
|
||||
// Pe32PlusOptionalHeader, so we don't use those types here.
|
||||
return *peOptionalHeader;
|
||||
}
|
||||
|
||||
//
|
||||
// Header information
|
||||
//
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const char* PeCoffObjectFileReader<PeCoffClassTraits>::Architecture(
|
||||
ObjectFileBase obj_base) {
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
uint16_t arch = peHeader->mMachine;
|
||||
switch (arch) {
|
||||
case IMAGE_FILE_MACHINE_I386:
|
||||
return "x86";
|
||||
case IMAGE_FILE_MACHINE_ARM:
|
||||
return "arm";
|
||||
case IMAGE_FILE_MACHINE_MIPS16:
|
||||
case IMAGE_FILE_MACHINE_MIPSFPU:
|
||||
case IMAGE_FILE_MACHINE_MIPSFPU16:
|
||||
case IMAGE_FILE_MACHINE_WCEMIPSV2:
|
||||
return "mips";
|
||||
case IMAGE_FILE_MACHINE_POWERPC:
|
||||
case IMAGE_FILE_MACHINE_POWERPCFP:
|
||||
return "ppc";
|
||||
case IMAGE_FILE_MACHINE_AMD64:
|
||||
return "x86_64";
|
||||
default:
|
||||
fprintf(stderr, "unrecognized machine architecture: %d\n",
|
||||
peHeader->mMachine);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
bool PeCoffObjectFileReader<PeCoffClassTraits>::Endianness(
|
||||
ObjectFileBase obj_base,
|
||||
bool* big_endian) {
|
||||
// TODO: Not sure what big-endian PECOFF looks like: characteristics flag
|
||||
// IMAGE_FILE_BYTES_REVERSED_HI and/or certain machine types are big-endian
|
||||
*big_endian = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
typename PeCoffObjectFileReader<PeCoffClassTraits>::Addr
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetLoadingAddress(
|
||||
ObjectFileBase obj_base) {
|
||||
const PeOptionalHeader* peOptionalHeader = GetOptionalHeader(obj_base);
|
||||
return peOptionalHeader->mImageBase;
|
||||
}
|
||||
|
||||
//
|
||||
// Section enumeration and location
|
||||
//
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
int PeCoffObjectFileReader<PeCoffClassTraits>::GetNumberOfSections(
|
||||
ObjectFileBase obj_base) {
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
return peHeader->mNumberOfSections;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const typename PeCoffObjectFileReader<PeCoffClassTraits>::Section
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::FindSectionByIndex(
|
||||
ObjectFileBase obj_base, int i) {
|
||||
const PeSectionHeader* section_table = GetSectionTable(obj_base);
|
||||
return reinterpret_cast<const Section>(&(section_table[i]));
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const typename PeCoffObjectFileReader<PeCoffClassTraits>::Section
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::FindSectionByName(
|
||||
const char* section_name, ObjectFileBase obj_base) {
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
const PeSectionHeader* section_table = GetSectionTable(obj_base);
|
||||
const char* string_table = GetStringTable(obj_base);
|
||||
uint32_t string_table_length = *(reinterpret_cast<const uint32_t*>(string_table));
|
||||
|
||||
for (int s = 0; s < peHeader->mNumberOfSections; s++) {
|
||||
const char* name = section_table[s].mName;
|
||||
|
||||
// look up long section names in string table
|
||||
if (name[0] == '/') {
|
||||
unsigned int offset = ::strtoul(section_table[s].mName+1, NULL, 10);
|
||||
|
||||
if (offset > string_table_length)
|
||||
fprintf(stderr, "section name offset %d exceeds string table length",
|
||||
offset);
|
||||
else
|
||||
name = string_table + offset;
|
||||
}
|
||||
|
||||
if (::strcmp(section_name, name) == 0) {
|
||||
return reinterpret_cast<const Section>(&(section_table[s]));
|
||||
}
|
||||
}
|
||||
|
||||
// nothing found
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Section information
|
||||
//
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const uint8_t*
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetSectionPointer(
|
||||
ObjectFileBase obj_base, Section section) {
|
||||
return reinterpret_cast<const uint8_t*>(obj_base) + reinterpret_cast<const PeSectionHeader*>(section)->mPointerToRawData;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
typename PeCoffObjectFileReader<PeCoffClassTraits>::Offset
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetSectionSize(
|
||||
ObjectFileBase obj_base, Section section) {
|
||||
|
||||
// There are mSizeOfRawData bytes of data for the section in the mapped image
|
||||
// file. Return mVirtualSize if it's smaller.
|
||||
// This doesn't handle the case where mVirtualSize is larger and the section
|
||||
// should be zero padded, because we have nowhere to do that.
|
||||
if ((reinterpret_cast<const PeSectionHeader*>(section)->mVirtualSize) <
|
||||
(reinterpret_cast<const PeSectionHeader*>(section)->mSizeOfRawData))
|
||||
return reinterpret_cast<const PeSectionHeader*>(section)->mVirtualSize;
|
||||
|
||||
return reinterpret_cast<const PeSectionHeader*>(section)->mSizeOfRawData;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
typename PeCoffObjectFileReader<PeCoffClassTraits>::Offset
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetSectionRVA(
|
||||
ObjectFileBase obj_base, Section section) {
|
||||
return reinterpret_cast<const PeSectionHeader*>(section)->mVirtualAddress;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const char* PeCoffObjectFileReader<PeCoffClassTraits>::GetSectionName(
|
||||
ObjectFileBase obj_base,Section section) {
|
||||
const char* string_table = GetStringTable(obj_base);
|
||||
uint32_t string_table_length = *(reinterpret_cast<const uint32_t*>(string_table));
|
||||
const char* name = reinterpret_cast<const PeSectionHeader*>(section)->mName;
|
||||
|
||||
// look up long section names in string table
|
||||
if (name[0] == '/') {
|
||||
unsigned int offset = ::strtoul(name+1, NULL, 10);
|
||||
|
||||
if (offset > string_table_length)
|
||||
fprintf(stderr, "section name offset %d exceeds string table length",
|
||||
offset);
|
||||
else
|
||||
name = string_table + offset;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
//
|
||||
|
||||
template<class PeCoffClassTraits>
|
||||
bool PeCoffObjectFileReader<PeCoffClassTraits>::ExportedSymbolsToModule(
|
||||
ObjectFileBase obj_base, Module* module) {
|
||||
// locate the export table, if present
|
||||
const PeDataDirectory* data_directory_export_entry = GetDataDirectoryEntry(obj_base, PE_EXPORT_TABLE);
|
||||
if (data_directory_export_entry && data_directory_export_entry->mSize != 0) {
|
||||
const PeExportTable* export_table = reinterpret_cast<const PeExportTable*>(ConvertRVAToPointer(obj_base, data_directory_export_entry->mVirtualAddress));
|
||||
const uint32_t* eat = reinterpret_cast<const uint32_t*>(ConvertRVAToPointer(obj_base, export_table->mExportAddressTableRVA));
|
||||
const uint32_t* enpt = reinterpret_cast<const uint32_t*>(ConvertRVAToPointer(obj_base, export_table->mNamePointerRVA));
|
||||
const uint16_t* eot = reinterpret_cast<const uint16_t*>(ConvertRVAToPointer(obj_base, export_table->mOrdinalTableRVA));
|
||||
|
||||
// process the export name pointer table
|
||||
for (uint32_t i = 0; i < export_table->mNumberofNamePointers; i++) {
|
||||
// look up the name for the export
|
||||
uint32_t export_name_rva = enpt[i];
|
||||
if (export_name_rva == 0)
|
||||
continue;
|
||||
const char* export_name = reinterpret_cast<const char*>(ConvertRVAToPointer(obj_base, export_name_rva));
|
||||
|
||||
// find the corresponding export address table entry
|
||||
uint16_t export_ordinal = eot[i];
|
||||
if ((export_ordinal < export_table->mOrdinalBase) ||
|
||||
(export_ordinal >= (export_table->mOrdinalBase + export_table->mAddressTableEntries))) {
|
||||
fprintf(stderr, "exported ordinal %d out of range for EAT!\n", export_ordinal);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t eat_index = export_ordinal - export_table->mOrdinalBase;
|
||||
uint32_t export_rva = eat[eat_index];
|
||||
|
||||
// if the export's address lies inside the export table, it's a forwarded
|
||||
// export, which we can ignore
|
||||
if ((export_rva >= data_directory_export_entry->mVirtualAddress) &&
|
||||
(export_rva < (data_directory_export_entry->mVirtualAddress + data_directory_export_entry->mSize)))
|
||||
continue;
|
||||
|
||||
Module::Extern* ext = new Module::Extern;
|
||||
ext->name = export_name;
|
||||
ext->address = export_rva + GetLoadingAddress(obj_base);
|
||||
module->AddExtern(ext);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// report if a COFF symbol table exists, but we don't use it (yet)
|
||||
// According to the PECOFF spec. COFF debugging information is deprecated.
|
||||
// We don't know of any tools which produce that and don't produce DWARF or
|
||||
// MS CodeView debug information.
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
if (peHeader->mPointerToSymbolTable) {
|
||||
fprintf(stderr, "COFF debug symbols present but are not implemented\n");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class PeCoffClassTraits>
|
||||
string
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::FileIdentifierFromMappedFile(
|
||||
ObjectFileBase obj_file) {
|
||||
uint8_t identifier[kMDGUIDSize];
|
||||
uint32_t age;
|
||||
|
||||
if (!PeCoffFileID::PeCoffFileIdentifierFromMappedFile(obj_file, identifier, &age))
|
||||
return "";
|
||||
|
||||
// Endian-ness swap to match dump processor expectation.
|
||||
uint8_t identifier_swapped[kMDGUIDSize];
|
||||
memcpy(identifier_swapped, identifier, kMDGUIDSize);
|
||||
uint32_t* data1 = reinterpret_cast<uint32_t*>(identifier_swapped);
|
||||
*data1 = htonl(*data1);
|
||||
uint16_t* data2 = reinterpret_cast<uint16_t*>(identifier_swapped + 4);
|
||||
*data2 = htons(*data2);
|
||||
uint16_t* data3 = reinterpret_cast<uint16_t*>(identifier_swapped + 6);
|
||||
*data3 = htons(*data3);
|
||||
|
||||
// Format the file identifier in IDENTIFIER as a UUID with the
|
||||
// dashes removed.
|
||||
char identifier_str[40];
|
||||
int buffer_idx = 0;
|
||||
for (int idx = 0; idx < kMDGUIDSize; ++idx) {
|
||||
int hi = (identifier_swapped[idx] >> 4) & 0x0F;
|
||||
int lo = (identifier_swapped[idx]) & 0x0F;
|
||||
|
||||
identifier_str[buffer_idx++] = (hi >= 10) ? 'A' + hi - 10 : '0' + hi;
|
||||
identifier_str[buffer_idx++] = (lo >= 10) ? 'A' + lo - 10 : '0' + lo;
|
||||
}
|
||||
identifier_str[buffer_idx] = 0;
|
||||
string id = identifier_str;
|
||||
|
||||
// Append age
|
||||
char age_string[9];
|
||||
snprintf(age_string, sizeof(age_string) / sizeof(age_string[0]), "%X", age);
|
||||
id += age_string;
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
//
|
||||
// Helper functions for PeCoffFileID
|
||||
//
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
bool PeCoffObjectFileReader<PeCoffClassTraits>::GetBuildID(
|
||||
ObjectFileBase obj_base,
|
||||
uint8_t identifier[kMDGUIDSize],
|
||||
uint32_t* age) {
|
||||
// locate the debug directory, if present
|
||||
const PeDataDirectory* data_directory_debug_entry = GetDataDirectoryEntry(obj_base, PE_DEBUG_DATA);
|
||||
if (!data_directory_debug_entry)
|
||||
return false;
|
||||
|
||||
uint32_t debug_directory_size = data_directory_debug_entry->mSize;
|
||||
if (debug_directory_size == 0)
|
||||
return false;
|
||||
|
||||
const PeDebugDirectory* debug_directory = reinterpret_cast<const PeDebugDirectory*>(ConvertRVAToPointer(obj_base, data_directory_debug_entry->mVirtualAddress));
|
||||
if (debug_directory == NULL) {
|
||||
fprintf(stderr, "No section containing the debug directory VMA could be found\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// search the debug directory for a codeview entry
|
||||
for (int i = 0; i < debug_directory_size/sizeof(PeDebugDirectory); i++) {
|
||||
if (debug_directory[i].mType == IMAGE_DEBUG_TYPE_CODEVIEW) {
|
||||
// interpret the codeview record to get build-id
|
||||
const CvInfoPbd70* codeview_record = reinterpret_cast<const CvInfoPbd70*>
|
||||
(obj_base + debug_directory[i].mPointerToRawData);
|
||||
if ((codeview_record->mCvSignature) == CODEVIEW_PDB70_CVSIGNATURE) {
|
||||
memcpy(identifier, codeview_record->mSignature, kMDGUIDSize);
|
||||
*age = codeview_record->mAge;
|
||||
return true;
|
||||
} else {
|
||||
fprintf(stderr, "Unhandled codeview signature %x\n",
|
||||
codeview_record->mCvSignature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "No codeview entry in debug directory\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
bool PeCoffObjectFileReader<PeCoffClassTraits>::HashTextSection(
|
||||
ObjectFileBase obj_base,
|
||||
uint8_t identifier[kMDGUIDSize]) {
|
||||
Section text_section;
|
||||
Offset text_size;
|
||||
|
||||
if (!(text_section = FindSectionByName(".text", obj_base)) ||
|
||||
((text_size = GetSectionSize(obj_base, text_section)) == 0))
|
||||
return false;
|
||||
|
||||
memset(identifier, 0, kMDGUIDSize);
|
||||
const uint8_t* ptr = GetSectionPointer(obj_base, text_section);
|
||||
const uint8_t* ptr_end = ptr + std::min(text_size, 4096U);
|
||||
while (ptr < ptr_end) {
|
||||
for (unsigned i = 0; i < kMDGUIDSize; i++)
|
||||
identifier[i] ^= ptr[i];
|
||||
ptr += kMDGUIDSize;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// Private implementation helper functions
|
||||
//
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const PeHeader* PeCoffObjectFileReader<PeCoffClassTraits>::GetHeader(
|
||||
ObjectFileBase obj_base) {
|
||||
const uint32_t* peOffsetPtr = reinterpret_cast<const uint32_t*>(obj_base +
|
||||
IMAGE_FILE_HEADER_OFFSET);
|
||||
const PeHeader* peHeader = reinterpret_cast<const PeHeader*>(obj_base+*peOffsetPtr);
|
||||
return peHeader;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const typename PeCoffObjectFileReader<PeCoffClassTraits>::PeOptionalHeader*
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetOptionalHeader(
|
||||
ObjectFileBase obj_base) {
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
PeOptionalHeader* peOptionalHeader = (PeOptionalHeader*) ((uint32_t*)peHeader + 6);
|
||||
return peOptionalHeader;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const PeSectionHeader*
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetSectionTable(
|
||||
ObjectFileBase obj_base) {
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
const PeOptionalHeader* peOptionalHeader = GetOptionalHeader(obj_base);
|
||||
|
||||
// section table immediately follows optional header
|
||||
const PeSectionHeader* section_table = reinterpret_cast<const PeSectionHeader*>
|
||||
(reinterpret_cast<const uint8_t*>(peOptionalHeader) + peHeader->mSizeOfOptionalHeader);
|
||||
return section_table;
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const char* PeCoffObjectFileReader<PeCoffClassTraits>::GetStringTable(
|
||||
ObjectFileBase obj_base) {
|
||||
const PeHeader* peHeader = GetHeader(obj_base);
|
||||
|
||||
// string table immediately follows symbol table
|
||||
uint32_t string_table_offset = peHeader->mPointerToSymbolTable + peHeader->mNumberOfSymbols*sizeof(PeSymbol);
|
||||
const char* string_table = reinterpret_cast<const char*>(obj_base) + string_table_offset;
|
||||
return string_table;
|
||||
}
|
||||
|
||||
template<class PeCoffClassTraits>
|
||||
const PeDataDirectory*
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::GetDataDirectoryEntry(
|
||||
ObjectFileBase obj_base, int entry) {
|
||||
const PeOptionalHeader* peOptionalHeader = GetOptionalHeader(obj_base);
|
||||
|
||||
// the data directory immediately follows the optional header
|
||||
const PeDataDirectory* data_directory = reinterpret_cast<const PeDataDirectory*>(&peOptionalHeader->mDataDirectory[0]);
|
||||
uint32_t data_directory_size = peOptionalHeader->mNumberOfRvaAndSizes;
|
||||
|
||||
// locate the required directory entry, if present
|
||||
if (data_directory_size < entry)
|
||||
return NULL;
|
||||
|
||||
return &data_directory[entry];
|
||||
}
|
||||
|
||||
template<typename PeCoffClassTraits>
|
||||
const uint8_t*
|
||||
PeCoffObjectFileReader<PeCoffClassTraits>::ConvertRVAToPointer(
|
||||
ObjectFileBase obj_base,
|
||||
Offset rva) {
|
||||
// find which section contains the rva to compute it's mapped address
|
||||
const PeSectionHeader* section_table = GetSectionTable(obj_base);
|
||||
for (int s = 0; s < GetNumberOfSections(obj_base); s++) {
|
||||
const PeSectionHeader* section = &(section_table[s]);
|
||||
|
||||
if ((rva >= section->mVirtualAddress) &&
|
||||
(rva < (section->mVirtualAddress + section->mSizeOfRawData)))
|
||||
{
|
||||
uint32_t offset = rva - section->mVirtualAddress;
|
||||
const uint8_t* pointer = GetSectionPointer(obj_base, (Section)section) + offset;
|
||||
return pointer;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "No section could be found containing RVA %x\n", rva);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// instantiation of templated classes
|
||||
template class PeCoffObjectFileReader<PeCoffClass32Traits>;
|
||||
template class PeCoffObjectFileReader<PeCoffClass64Traits>;
|
||||
|
||||
}
|
Reference in New Issue
Block a user