mirror of
https://github.com/NaC-L/Mergen.git
synced 2026-05-12 09:40:34 +00:00
ad41d97112
GEPLoadPass: - Check readMemory return value; previously used uninitialized memory as a constant replacement on failure (UB + silent miscompile) - Guard against non-integer load types; getIntegerBitWidth() asserts on float/vector/pointer types, causing a crash - Only process GEPs rooted on the lifter's memory base pointer, not arbitrary GEPs created by LLVM optimizations - Erase replaced LoadInsts and dead GEPs immediately instead of leaving dead instructions for the next DCE pass PromotePseudoStackPass: - Promote stack accesses both below AND above STACKP_VALUE; previously only captured below, missing return address, shadow space, and stack-passed arguments - Use explicit stack bounds [STACKP_VALUE-reserve, STACKP_VALUE+reserve] instead of isConcrete(), which would also capture PE image sections and create a multi-gigabyte alloca - Add stackReserve field to lifter class, set by configureDefaultMemoryPolicy - Guard against unsigned underflow in stackLower computation ReplaceTruncWithLoadPass: - Generalize from hardcoded i64->i32 to any integer narrowing; now also handles i32->i16, i16->i8, etc. - Erase original wide LoadInst when it has no remaining users Stack bounds consistency: - pageMap (markMemPaged/isMemPaged) now uses clamped stack reserve from lifter->stackReserve instead of raw PE header value, so pageMap, memoryPolicy, and PromotePseudoStackPass all agree on stack bounds - Changed pageMap, markMemPaged, isMemPaged from int64_t to uint64_t to match the actual address types and avoid signed/unsigned mismatch Cleanup: - Remove dead final_optpass declaration from PathSolver.h (no impl/callers) - Remove fragile name-based 'memory' argument fallback in run_opts; assert memoryAlloc is set instead
31 lines
1.3 KiB
C++
31 lines
1.3 KiB
C++
#pragma once
|
|
|
|
#include "LifterClass_Concolic.hpp"
|
|
#include <algorithm>
|
|
#include <cstdint>
|
|
|
|
inline void configureDefaultMemoryPolicy(lifterConcolic<>* lifter,
|
|
uint64_t stackReserve = 0x1000) {
|
|
lifter->memoryPolicy.setDefaultMode(MemoryAccessMode::SYMBOLIC);
|
|
|
|
for (auto& section : lifter->file.sections_v) {
|
|
const auto sectionStart = lifter->file.imageBase + section.virtual_address;
|
|
const auto sectionEnd = sectionStart + section.virtual_size;
|
|
|
|
// All PE sections are CONCRETE: initial values are known from the file.
|
|
// The concolic buffer tracks stores, so reads without prior stores
|
|
// correctly return the file's initial bytes.
|
|
lifter->memoryPolicy.addRange(sectionStart, sectionEnd,
|
|
MemoryAccessMode::CONCRETE);
|
|
}
|
|
|
|
// Use actual stack reserve from PE header instead of hardcoded 0x1000.
|
|
// Clamp to reasonable bounds: at least 0x1000, at most 0x100000 (1MB).
|
|
uint64_t clampedReserve = std::max(stackReserve, uint64_t(0x1000));
|
|
clampedReserve = std::min(clampedReserve, uint64_t(0x100000));
|
|
lifter->stackReserve = clampedReserve;
|
|
lifter->memoryPolicy.addRange(STACKP_VALUE - clampedReserve,
|
|
STACKP_VALUE + clampedReserve,
|
|
MemoryAccessMode::CONCRETE);
|
|
}
|