mirror of
https://github.com/NaC-L/Mergen.git
synced 2026-05-12 09:40:34 +00:00
4.7 KiB
4.7 KiB
Architecture Reference
Key Constants
| Constant | Value | Defined in |
|---|---|---|
STACKP_VALUE |
0x14FEA0 |
lifter/core/Includes.h |
| Stack reserve min | 0x1000 |
lifter/memory/MemoryPolicySetup.hpp (configureDefaultMemoryPolicy) |
| Stack reserve max | 0x100000 |
lifter/memory/MemoryPolicySetup.hpp (configureDefaultMemoryPolicy) |
Pipeline Order
| # | Function | File | Purpose |
|---|---|---|---|
| 1 | createRuntimeImageContext |
lifter/core/RuntimeImageContext.hpp |
Validates PE headers, builds RuntimeImageContext |
| 2 | createConfiguredLifterForRuntime |
lifter/core/LifterStages.hpp |
Calls loadFile, parses PE exports, auto-outlines export addresses |
| 3 | configureDefaultMemoryPolicy |
lifter/memory/MemoryPolicySetup.hpp |
Sets memoryPolicy (SYMBOLIC default, CONCRETE for PE sections + stack), clamps stackReserve to [0x1000, 0x100000] |
| 4 | prepareRuntimePagedMemory |
lifter/core/LifterPipelineStages.hpp |
Marks pageMap intervals for mapped memory regions |
| 5 | runSignatureStage |
lifter/core/LifterPipelineStages.hpp |
Signature-based analysis |
| 6 | Lift loop | lifter/core/LiftDriver.hpp |
Main lifting of instructions to LLVM IR |
| 7 | run_opts |
lifter/core/MergenPB.hpp |
Fixpoint optimization (see below) |
run_opts Fixpoint Loop
loop {
O1 pipeline
GEPLoadPass
ReplaceTruncWithLoadPass
PromotePseudoStackPass
PromotePseudoMemory
} until instruction count stabilizes (delta == 0)
Final O2 pipeline (runs once after fixpoint)
Termination: the loop compares instruction count before and after each iteration. When the count stops changing, the fixpoint is reached.
Custom Pass Summary
| Pass | Filters on | Produces | Description |
|---|---|---|---|
GEPLoadPass |
memory-base GEPs where: getPointerOperand() == mem, !isSymbolic, address_to_mapped_address != 0, isIntegerTy(), readMemory succeeds |
Constant integer values folded from PE image | Folds constant loads from the PE image through memory-base GEPs |
ReplaceTruncWithLoadPass |
trunc(load wide, ptr) patterns |
load narrow, ptr |
Rewrites wide-load-then-truncate into narrow load; valid on little-endian |
PromotePseudoStackPass |
memory-base GEPs in [STACKP_VALUE - reserve, STACKP_VALUE + reserve] via isStackAddress() |
stackmemory alloca GEPs |
Replaces pseudo-stack memory accesses with real stack alloca operations |
PromotePseudoMemory |
Remaining memory-base GEPs (not handled by above passes) |
inttoptr |
Converts leftover pseudo-memory GEPs to raw pointer operations |
Pass order matters: GEPLoadPass must run before PromotePseudoMemory, otherwise concrete PE loads get converted to inttoptr and are lost.
InlinePolicy
- CRTP framework: default policy inlines everything.
- Outline set:
addAddress(va)registers a VA for outlining (i.e., not inlined). - Check site:
Semantics_ControlFlow.ipp:202— when a call target is constant-resolved, the inline policy is consulted. - CLI:
--outline <addrs>accepts comma-separated hex addresses, parsed inUtils.cpp, stored inParseResult::outlineAddresses. - PE export auto-outline: export addresses are automatically added to the outline set in
createConfiguredLifterForRuntime. Forwarded exports are filtered out by checking if the RVA falls within the export directory range.
Memory Subsystem
FileReader
CRTP base with concrete implementations x86FileReader and x86_64FileReader.
| Method | Returns | Failure value |
|---|---|---|
RvaToFileOffset |
file offset | 0 |
readMemory |
bool |
false |
address_to_mapped_address |
mapped address | 0 |
MemoryPolicy
| Region | Policy |
|---|---|
| Default | SYMBOLIC |
| PE sections | CONCRETE |
| Stack | CONCRETE |
Set by configureDefaultMemoryPolicy in lifter/memory/MemoryPolicySetup.hpp.
pageMap
std::map<uint64_t, uint64_t> — interval map of paged memory regions.
markMemPaged(start, end)— inserts an interval.isMemPaged— usesupper_boundthen decrements iterator to check containment.
stackReserve
Set by configureDefaultMemoryPolicy, clamped to [0x1000, 0x100000]. Consumed by:
PromotePseudoStackPass— defines the stack address window aroundSTACKP_VALUEprepareRuntimePagedMemory— marks the stack region inpageMap
PE Parsing
- Header types come from the linuxpe library.
RvaToFileOffsetreturns0on failure — callers must check before using the offset.- Export directory is parsed in
createConfiguredLifterForRuntime; forwarded exports are detected by checking if the export RVA falls within the export directory VA range. RuntimeImageContextis validated increateRuntimeImageContext(step 1 of the pipeline).