HeapEntry解码过程

在调试堆时对HeapEntry解码的过程,记录下来以便以后学习用到。
在Win7上调试堆时,会发现_HEAP 增加了两个标志,一个是EncodeFlagMask,另一个是Encoding,其中EncodeFlagMask标明了堆头部是否经过了编码,这个字段的初值为0x100000,由RtlpCreateHeapEncoding()函数设置。而Encoding是一个_HEAP_ENTRY结构体的指针。


举一个例子来说:


0:005>!heap -a 1

Index   Address  Name      Debugging options enabled

  1:   003d0000

    Segment at 003d0000 to 004d0000 (00100000 bytes committed)

    Segment at 02c70000 to 02d70000 (00020000 bytes committed)

    Flags:                00000002

    ForceFlags:           00000000

    Granularity:          8 bytes

    Segment Reserve:      00200000

    Segment Commit:       00002000

    DeCommit Block Thres: 00000800

    DeCommit Total Thres: 00002000

    Total Free Size:      00002433

    Max. Allocation Size: 7ffdefff

    Lock Variable at:     003d0138

    Next TagIndex:        0000

    Maximum TagIndex:     0000

    Tag Entries:          00000000

    PsuedoTag Entries:    00000000

    Virtual Alloc List:   003d00a0

    Uncommitted ranges:   003d0090

            02c90000: 000e0000  (917504 bytes)

    FreeList[ 00 ] at 003d00c4: 02c81fe8 . 004537a8 

        004537a0: 00108 . 00010 [100] - free

        004a7fc0: 00190 . 00010 [100] - free

        00453678: 00098 . 00010 [100] - free

        0044b0e8: 000c8 . 00010 [100] - free

        00418bd8: 00068 . 00010 [100] - free

        00413230: 00040 . 00010 [100] - free

        00403b48: 00040 . 00010 [100] - free

        0046f620: 00130 . 00018 [100] - free

        00440e50: 000f0 . 00018 [100] - free

        0044bb50: 001c8 . 00018 [100] - free

        0043dc10: 00140 . 00018 [120] - free

        0043ca78: 00128 . 00018 [100] - free

        00474be0: 000e8 . 00018 [100] - free

        00452358: 00070 . 00018 [100] - free

        0042ebc8: 00090 . 00018 [100] - free

        004178c0: 00070 . 00018 [100] - free

        00414e40: 00040 . 00018 [100] - free

        004323e0: 00088 . 00020 [120] - free

        0041a608: 00040 . 00020 [100] - free

        004158a8: 00070 . 00020 [100] - free

        0040ff50: 00128 . 00020 [100] - free

        004a2280: 00160 . 00028 [100] - free

        00415ef0: 00068 . 00028 [100] - free

        0047b748: 00678 . 00030 [100] - free


可以看到-a列出了所有的Heap Entries,这里只截取了其中的一部分,接下来以第一个Entry为例进行说明,先看下_heap_entry的结构:

ntdll!_HEAP_ENTRY

   +0x000 Size             : Uint2B

   +0x002 Flags            : UChar

   +0x003 SmallTagIndex    : UChar

   +0x000 SubSegmentCode   : Ptr32 Void

   +0x004 PreviousSize     : Uint2B

   +0x006 SegmentOffset    : UChar

   +0x006 LFHFlags         : UChar

   +0x007 UnusedBytes      : UChar

   +0x000 FunctionIndex    : Uint2B

   +0x002 ContextValue     : Uint2B

   +0x000 InterceptorValue : Uint4B

   +0x004 UnusedBytesLength : Uint2B

   +0x006 EntryOffset      : UChar

   +0x007 ExtendedBlockSignature : UChar

   +0x000 Code1            : Uint4B

   +0x004 Code2            : Uint2B

   +0x006 Code3            : UChar

   +0x007 Code4            : UChar

   +0x000 AgregateCode     : Uint8B

 

再来看下实际数据:

0:005> dd 004537a0

004537a0  61329aa1 00007314 004a7fc8 003d00c4

004537b0  7e339abf 08007337 7606479c 76064b78

004537c0  00000002 760647ec 00000001 00000000

004537d0  00449890 ffffffff 00000000 00000000

004537e0  00000000 00000000 00000000 00000000

004537f0  760647e0 00000001 00000002 004498b8

00453800  ffffffff 00000000 00000000 00000000

00453810  00000000 0046e848 00000000 00452420

 

接下来定位到Encoding处,进行解码操作:

ntdll!_HEAP

   +0x000 Entry            : _HEAP_ENTRY

   +0x008 SegmentSignature : 0xffeeffee

   +0x00c SegmentFlags     : 0

   +0x010 SegmentListEntry : _LIST_ENTRY [ 0x2c70010 - 0x3d00a8 ]

   +0x018 Heap             : 0x003d0000 _HEAP

   +0x01c BaseAddress      : 0x003d0000

   +0x020 NumberOfPages    : 0x100

   +0x024 FirstEntry       : 0x003d0588 _HEAP_ENTRY

   +0x028 LastValidEntry   : 0x004d0000 _HEAP_ENTRY

   +0x02c NumberOfUnCommittedPages : 0

   +0x030 NumberOfUnCommittedRanges : 1

   +0x034 SegmentAllocatorBackTraceIndex : 0

   +0x036 Reserved         : 0

   +0x038 UCRSegmentList   : _LIST_ENTRY [ 0x4cfff0 - 0x4cfff0 ]

   +0x040 Flags            : 2

   +0x044 ForceFlags       : 0

   +0x048 CompatibilityFlags : 0

   +0x04c EncodeFlagMask   : 0x100000

   +0x050 Encoding         : _HEAP_ENTRY

   +0x058 PointerKey       : 0x1ff34c7d

   +0x05c Interceptor      : 0

   +0x060 VirtualMemoryThreshold : 0xfe00

   +0x064 Signature        : 0xeeffeeff

   +0x068 SegmentReserve   : 0x200000

   +0x06c SegmentCommit    : 0x2000

   +0x070 DeCommitFreeBlockThreshold : 0x800

   +0x074 DeCommitTotalFreeThreshold : 0x2000

   +0x078 TotalFreeSize    : 0x2433

   +0x07c MaximumAllocationSize : 0x7ffdefff

   +0x080 ProcessHeapsListIndex : 1

   +0x082 HeaderValidateLength : 0x138

   +0x084 HeaderValidateCopy : (null)

   +0x088 NextAvailableTagIndex : 0

   +0x08a MaximumTagIndex  : 0

   +0x08c TagEntries       : (null)

   +0x090 UCRList          : _LIST_ENTRY [ 0x2c8ffe8 - 0x2c8ffe8 ]

   +0x098 AlignRound       : 0xf

   +0x09c AlignMask        : 0xfffffff8

   +0x0a0 VirtualAllocdBlocks : _LIST_ENTRY [ 0x3d00a0 - 0x3d00a0 ]

   +0x0a8 SegmentList      : _LIST_ENTRY [ 0x3d0010 - 0x2c70010 ]

   +0x0b0 AllocatorBackTraceIndex : 0

   +0x0b4 NonDedicatedListLength : 0

   +0x0b8 BlocksIndex      : 0x003d0150

   +0x0bc UCRIndex         : 0x003d0590

   +0x0c0 PseudoTagEntries : (null)

   +0x0c4 FreeLists        : _LIST_ENTRY [ 0x4537a8 - 0x2c81fe8 ]

   +0x0cc LockVariable     : 0x003d0138 _HEAP_LOCK

   +0x0d0 CommitRoutine    : 0x1ff34c7d     long  +1ff34c7d

   +0x0d4 FrontEndHeap     : 0x003d66b0

   +0x0d8 FrontHeapLockCount : 0

   +0x0da FrontEndHeapType : 0x2 ''

   +0x0dc Counters         : _HEAP_COUNTERS

   +0x130 TuningParameters : _HEAP_TUNING_PARAMETERS

0:005> dd 003d0000+50

003d0050  63329aa3 00007335 1ff34c7d 00000000

003d0060  0000fe00 eeffeeff 00200000 00002000

003d0070  00000800 00002000 00002433 7ffdefff

003d0080  01380001 00000000 00000000 00000000

003d0090  02c8ffe8 02c8ffe8 0000000f fffffff8

003d00a0  003d00a0 003d00a0 003d0010 02c70010

003d00b0  00000000 00000000 003d0150 003d0590

003d00c0  00000000 004537a8 02c81fe8 003d0138

 堆块入口:

0:005> dd 004537a0

004537a0  61329aa1 00007314 004a7fc8 003d00c4

004537b0  7e339abf 08007337 7606479c 76064b78

004537c0  00000002 760647ec 00000001 00000000

004537d0  00449890 ffffffff 00000000 00000000

004537e0  00000000 00000000 00000000 00000000

004537f0  760647e0 00000001 00000002 004498b8

00453800  ffffffff 00000000 00000000 00000000

00453810  00000000 0046e848 00000000 00452420

 

进行异或操作:

0:005> ? 9aa1^9aa3

Evaluate expression: 2 = 00000002

将结果乘以粒度大小(8字节):

0:005> ?2*8

Evaluate expression: 16 = 00000010

最终得到正确的Size大小,这与!heap -a 1中显示的一致了。

Transformer是一种基于自注意力机制的序列到序列模型,它由编码器和解码器组成。下面是Transformer的编码器和解码器的大致过程: 编码器: 1. 输入序列经过一个嵌入层,将每个输入元素映射为一个高维向量表示。 2. 对输入序列进行位置编码,以在模型中引入位置信息。 3. 进行多层的自注意力机制(Self-Attention)计算,其中每个位置的表示将参与对所有其他位置的加权求和。这允许模型在处理序列时对不同位置之间的依赖关系进行建模。 4. 在自注意力计算后,通过前馈神经网络(Feed-Forward Network)对每个位置的表示进行非线性变换。 5. 重复上述自注意力和前馈网络层的堆叠,以增加模型的深度。 6. 编码器输出为最终的编码表示,可用于后续任务。 解码器: 1. 类似于编码器,解码器也包含嵌入层和位置编码层。 2. 解码器还引入了一个额外的注意力机制,称为编码-解码注意力(Encoder-Decoder Attention)。该注意力机制允许解码器根据编码器输出的信息对输入序列进行关注,并将其用于生成下一个输出。 3. 在解码器中,也进行多层的自注意力计算和前馈网络层的堆叠,以允许模型对输出序列中的依赖关系进行建模。 4. 最后,通过一个线性变换和Softmax函数将解码器的输出映射为概率分布,用于生成下一个预测的输出。 编码器和解码器之间通过编码-解码注意力机制进行交互,使得解码器能够在生成每个输出时对输入序列进行适当的关注。 总的来说,Transformer模型通过自注意力机制和前馈网络层的堆叠,以及编码-解码注意力机制,实现了对序列数据的编码和解码过程。这种基于注意力机制的设计使得Transformer在处理文本、机器翻译等序列任务时取得了很好的效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值