refactor: forward information to the parse functions instead of adding attribute

This commit is contained in:
Romain Thomas
2026-10-10 07:32:17 +02:00
parent 42252ba5e8
commit e71901e79a
8 changed files with 47 additions and 47 deletions
+3 -1
View File
@@ -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;
-18
View File
@@ -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),
+8 -6
View File
@@ -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
View File
@@ -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);
}