mirror of
https://github.com/lief-project/LIEF.git
synced 2026-10-11 22:09:53 +00:00
refactor: forward information to the parse functions instead of adding attribute
This commit is contained in:
@@ -32,8 +32,10 @@ class Parser;
|
||||
/// This class is the base class for any exception or runtime function entry
|
||||
class LIEF_API ExceptionInfo {
|
||||
public:
|
||||
static std::unique_ptr<ExceptionInfo> parse(Parser& ctx, BinaryStream& strm);
|
||||
static std::unique_ptr<ExceptionInfo> parse(Parser& ctx, BinaryStream& strm,
|
||||
uint64_t size, uint64_t nb_scopes);
|
||||
static std::unique_ptr<ExceptionInfo> parse(Parser& ctx, BinaryStream& strm,
|
||||
uint64_t size, uint64_t nb_scopes,
|
||||
Header::MACHINE_TYPES arch);
|
||||
|
||||
ExceptionInfo() = delete;
|
||||
|
||||
@@ -195,27 +195,10 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
|
||||
std::unique_ptr<SpanStream> stream_from_rva(uint32_t rva, size_t size = 0);
|
||||
|
||||
bool consume_exception_scopes(size_t count) {
|
||||
if (count > exception_scopes_budget_) {
|
||||
exception_scopes_budget_ = 0;
|
||||
return false;
|
||||
}
|
||||
exception_scopes_budget_ -= count;
|
||||
return true;
|
||||
}
|
||||
|
||||
void record_relocation(uint32_t rva, span<const uint8_t> data);
|
||||
ok_error_t record_delta_relocation(uint32_t rva, int64_t delta, size_t size);
|
||||
|
||||
private:
|
||||
// Caps total AArch64 epilog scopes to bound allocations on a malformed table
|
||||
void seed_exception_scopes_budget(size_t table_size) {
|
||||
static constexpr size_t PDATA_ENTRY_SIZE = 2 * sizeof(uint32_t);
|
||||
static constexpr size_t MAX_SCOPES_PER_FUNCTION = 32;
|
||||
exception_scopes_budget_ = (table_size / PDATA_ENTRY_SIZE) *
|
||||
MAX_SCOPES_PER_FUNCTION;
|
||||
}
|
||||
|
||||
struct relocation_t {
|
||||
uint64_t size = 0;
|
||||
uint64_t value = 0;
|
||||
@@ -309,7 +292,6 @@ class LIEF_API Parser : public LIEF::Parser {
|
||||
std::map<uint32_t, ExceptionInfo*> memoize_exception_info_;
|
||||
std::map<uint32_t, relocation_t> dyn_hdr_relocs_;
|
||||
std::vector<std::pair<ExceptionInfo*, uint32_t>> unresolved_chains_;
|
||||
size_t exception_scopes_budget_ = 0;
|
||||
ParserConfig config_;
|
||||
};
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ class LIEF_API UnpackedFunction : public RuntimeFunctionAArch64 {
|
||||
using it_const_epilog_scopes = const_ref_iterator<const epilog_scopes_t&>;
|
||||
|
||||
static std::unique_ptr<UnpackedFunction> parse(Parser& ctx, BinaryStream& strm,
|
||||
uint64_t size, uint64_t nb_scopes,
|
||||
uint32_t xdata_rva, uint32_t rva);
|
||||
|
||||
UnpackedFunction(uint32_t rva, uint32_t length) :
|
||||
|
||||
@@ -45,8 +45,8 @@ class LIEF_API RuntimeFunctionAArch64 : public ExceptionInfo {
|
||||
RESERVED = 3,
|
||||
};
|
||||
|
||||
static std::unique_ptr<RuntimeFunctionAArch64> parse(Parser& ctx,
|
||||
BinaryStream& strm);
|
||||
static std::unique_ptr<RuntimeFunctionAArch64>
|
||||
parse(Parser& ctx, BinaryStream& strm, uint64_t size, uint64_t nb_scopes);
|
||||
|
||||
RuntimeFunctionAArch64(uint64_t RVA, uint32_t length, PACKED_FLAGS flag) :
|
||||
ExceptionInfo(ARCH::ARM64, RVA),
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
|
||||
namespace LIEF::PE {
|
||||
|
||||
std::unique_ptr<ExceptionInfo> ExceptionInfo::parse(Parser& ctx,
|
||||
BinaryStream& strm,
|
||||
Header::MACHINE_TYPES arch) {
|
||||
std::unique_ptr<ExceptionInfo>
|
||||
ExceptionInfo::parse(Parser& ctx, BinaryStream& strm, uint64_t size,
|
||||
uint64_t nb_scopes, Header::MACHINE_TYPES arch) {
|
||||
uint64_t pos = strm.pos();
|
||||
switch (arch) {
|
||||
case Header::MACHINE_TYPES::AMD64:
|
||||
@@ -38,7 +38,7 @@ std::unique_ptr<ExceptionInfo> ExceptionInfo::parse(Parser& ctx,
|
||||
}
|
||||
case Header::MACHINE_TYPES::ARM64:
|
||||
{
|
||||
if (auto F = RuntimeFunctionAArch64::parse(ctx, strm)) {
|
||||
if (auto F = RuntimeFunctionAArch64::parse(ctx, strm, size, nb_scopes)) {
|
||||
F->offset(pos);
|
||||
return F;
|
||||
}
|
||||
@@ -51,9 +51,11 @@ std::unique_ptr<ExceptionInfo> ExceptionInfo::parse(Parser& ctx,
|
||||
}
|
||||
|
||||
std::unique_ptr<ExceptionInfo> ExceptionInfo::parse(Parser& ctx,
|
||||
BinaryStream& strm) {
|
||||
BinaryStream& strm,
|
||||
uint64_t size,
|
||||
uint64_t nb_scopes) {
|
||||
const Header::MACHINE_TYPES arch = ctx.bin().header().machine();
|
||||
return parse(ctx, strm, arch);
|
||||
return parse(ctx, strm, size, nb_scopes, arch);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+12
-6
@@ -46,6 +46,7 @@
|
||||
#include "LIEF/PE/debug/PogoEntry.hpp"
|
||||
#include "LIEF/PE/debug/Repro.hpp"
|
||||
#include "LIEF/PE/debug/VCFeature.hpp"
|
||||
#include "LIEF/PE/exceptions_info/AArch64/UnpackedFunction.hpp"
|
||||
#include "LIEF/PE/exceptions_info/RuntimeFunctionX64.hpp"
|
||||
#include "LIEF/PE/signature/Signature.hpp"
|
||||
#include "LIEF/PE/signature/SignatureParser.hpp"
|
||||
@@ -761,15 +762,17 @@ ok_error_t Parser::parse_exceptions() {
|
||||
return make_error_code(lief_errors::corrupted);
|
||||
}
|
||||
|
||||
seed_exception_scopes_budget(pdata.size());
|
||||
|
||||
uint64_t nb_scopes = 0;
|
||||
[[maybe_unused]] size_t idx = 0;
|
||||
while (*stream) {
|
||||
auto ptr = ExceptionInfo::parse(*this, *stream);
|
||||
auto ptr = ExceptionInfo::parse(*this, *stream, pdata.size(), nb_scopes);
|
||||
if (ptr == nullptr) {
|
||||
LIEF_INFO("Failed to parse exception info index: {}", idx);
|
||||
break;
|
||||
}
|
||||
if (const auto* unpacked = ptr->as<unwind_aarch64::UnpackedFunction>()) {
|
||||
nb_scopes += unpacked->epilog_scopes().size();
|
||||
}
|
||||
ptr->offset(base_offset + ptr->offset());
|
||||
binary_->exceptions_.push_back(std::move(ptr));
|
||||
++idx;
|
||||
@@ -830,8 +833,6 @@ ok_error_t Parser::parse_chpe_exceptions() {
|
||||
|
||||
uint64_t base_offset = binary_->rva_to_offset(arm64->extra_rfe_table());
|
||||
|
||||
seed_exception_scopes_budget(arm64->extra_rfe_table_size());
|
||||
|
||||
Header::MACHINE_TYPES target_arch = bin().header().machine();
|
||||
switch (target_arch) {
|
||||
// ARM64EC
|
||||
@@ -848,13 +849,18 @@ ok_error_t Parser::parse_chpe_exceptions() {
|
||||
default: break;
|
||||
}
|
||||
|
||||
uint64_t nb_scopes = 0;
|
||||
[[maybe_unused]] size_t idx = 0;
|
||||
while (*stream) {
|
||||
auto ptr = ExceptionInfo::parse(*this, *stream, target_arch);
|
||||
auto ptr = ExceptionInfo::parse(*this, *stream, arm64->extra_rfe_table_size(),
|
||||
nb_scopes, target_arch);
|
||||
if (ptr == nullptr) {
|
||||
LIEF_INFO("Failed to parse exception info index: {}", idx);
|
||||
break;
|
||||
}
|
||||
if (const auto* unpacked = ptr->as<unwind_aarch64::UnpackedFunction>()) {
|
||||
nb_scopes += unpacked->epilog_scopes().size();
|
||||
}
|
||||
ptr->offset(base_offset + ptr->offset());
|
||||
|
||||
binary_->exceptions_.push_back(std::move(ptr));
|
||||
|
||||
@@ -13,13 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "LIEF/PE/exceptions_info/AArch64/UnpackedFunction.hpp"
|
||||
#include "LIEF/BinaryStream/BinaryStream.hpp"
|
||||
#include "LIEF/BinaryStream/SpanStream.hpp"
|
||||
#include "LIEF/span.hpp"
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "LIEF/PE/Parser.hpp"
|
||||
#include "LIEF/BinaryStream/BinaryStream.hpp"
|
||||
#include "LIEF/BinaryStream/SpanStream.hpp"
|
||||
#include "LIEF/PE/exceptions_info/AArch64/UnpackedFunction.hpp"
|
||||
#include "LIEF/span.hpp"
|
||||
|
||||
#include "LIEF/PE/exceptions_info/internal_arm64.hpp"
|
||||
#include "PE/exceptions_info/UnwindAArch64Decoder.hpp"
|
||||
|
||||
@@ -30,11 +31,16 @@ namespace LIEF::PE::unwind_aarch64 {
|
||||
|
||||
using epilog_scope_t = UnpackedFunction::epilog_scope_t;
|
||||
|
||||
std::unique_ptr<UnpackedFunction> UnpackedFunction::parse(Parser& ctx,
|
||||
BinaryStream& strm,
|
||||
uint32_t xdata_rva,
|
||||
uint32_t rva) {
|
||||
std::unique_ptr<UnpackedFunction>
|
||||
UnpackedFunction::parse(Parser& /*ctx*/, BinaryStream& strm, uint64_t size,
|
||||
uint64_t nb_scopes, uint32_t xdata_rva, uint32_t rva) {
|
||||
static constexpr auto WIDTH = 20;
|
||||
|
||||
static constexpr size_t PDATA_ENTRY_SIZE = 2 * sizeof(uint32_t);
|
||||
static constexpr size_t MAX_SCOPES_PER_FUNCTION = 32;
|
||||
|
||||
const uint64_t max_scopes = (size / PDATA_ENTRY_SIZE) * MAX_SCOPES_PER_FUNCTION;
|
||||
|
||||
details::arm64_unpacked_t unpacked;
|
||||
|
||||
LIEF_DEBUG("Parsing unpacked function {:#010x}", rva);
|
||||
@@ -91,9 +97,8 @@ std::unique_ptr<UnpackedFunction> UnpackedFunction::parse(Parser& ctx,
|
||||
/// is required.
|
||||
std::vector<uint32_t> scopes;
|
||||
if (unpacked.E() == 0) {
|
||||
if (!ctx.consume_exception_scopes(ecount)) {
|
||||
LIEF_DEBUG("Epilog scope budget exhausted (record claims {} scopes)",
|
||||
ecount);
|
||||
if (nb_scopes + ecount > max_scopes) {
|
||||
LIEF_DEBUG("Epilog scope out of ranges (requested {} scopes)", ecount);
|
||||
return func;
|
||||
}
|
||||
func->epilog_scopes_offset_ = strm.pos() - strm_offset;
|
||||
|
||||
@@ -29,7 +29,8 @@
|
||||
namespace LIEF::PE {
|
||||
|
||||
std::unique_ptr<RuntimeFunctionAArch64>
|
||||
RuntimeFunctionAArch64::parse(Parser& ctx, BinaryStream& strm) {
|
||||
RuntimeFunctionAArch64::parse(Parser& ctx, BinaryStream& strm, uint64_t size,
|
||||
uint64_t nb_scopes) {
|
||||
auto rva_start = strm.read<uint32_t>();
|
||||
if (!rva_start) {
|
||||
LIEF_WARN("Failed to read exception info RVA start (line: {})", __LINE__);
|
||||
@@ -54,7 +55,8 @@ std::unique_ptr<RuntimeFunctionAArch64>
|
||||
if (flag == PACKED_FLAGS::UNPACKED) {
|
||||
uint32_t xdata_rva = details::xdata_unpacked_rva(*unwind_data);
|
||||
std::unique_ptr<SpanStream> xdata_strm = ctx.stream_from_rva(xdata_rva);
|
||||
return unwind_aarch64::UnpackedFunction::parse(ctx, *xdata_strm, xdata_rva,
|
||||
return unwind_aarch64::UnpackedFunction::parse(ctx, *xdata_strm, size,
|
||||
nb_scopes, xdata_rva,
|
||||
*rva_start);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user