Windows 7 Object Headers
2016-06-15 10:09
393 查看
This document describes the changes to the object header structure that have been made in Windows 7 and the areas of functionality these changes affect. It starts with a brief description of the layout of objects and the related data structures, the difference
between the legacy and the new object header structures, followed by a detailed description of the reason for the changes and the areas of functionality that are affected by these changes. This document refers to all versions of Windows before Windows 7 as
"older" versions as Windows. All debugger examples used in the document are on Windows Vista SP1 or Windows 7 kernel running on the X86 platform.
A structure becomes an object when the object manager, a component in the Windows kernel, puts headers before the start of the object, to provide a range of services including object naming, object reference counting, checking for security, using information
stored in these headers. The following figure shows the layout of objects and the associated headers:
As shown in the above figure, objects are allocated from either the paged or non-paged pool. The allocation always starts with a pool header, a structure of type nt!_POOL_HEADER. The pool header is then followed by optional object headers, which could be
of four different types - details of which are described later.The optional object headers are followed by a mandatory object header which is a structure of type nt!_OBJECT_HEADER and finally the object itself. This could be any of the 37 different object
types supported as of Windows Vista. Examples of objects inlcude events (nt!_KEVENT), semaphores (nt!_KSEMAPHORE), file objects (nt!_FILE_OBJECT), device objects (nt!_DEVICE_OBJECT). The last few bytes of the object header, the field OBJECT_HEADER->Body, overlap
with the actual object body. The OBJECT_HEADER->Type->TypeInfo.PoolType field determines which pool a particular type of objects would be allocated from this can be either PagedPool or NonPagedPool.
On Windows 7 and later version of Windows the "!object" command displays a slightly different output:
Examining the OBJECT_HEADER structure on the respective versions of Windows shows the reason for the debugger displaying "old version" and "new version". Following debugger output shows the OBJECT_HEADER on older versions of Windows. The fields below that
are highlighted are ones that have been removed from the OBJECT_HEADER structure in Windows 7:
The highlighted fields below are new to the OBJECT_HEADER structure in Windows 7:
operation on an object. This implied that no other object of that type in the entire system could be manipulated for the duration the object type lock was held. With Windows 7, due to the availability of the per-object lock (OBJET_HEADER->Lock), manipulating
one object does not prevent any other object from being manipulated simultaneously, including objects of the same type. The rest of the changes that have been made to the OBJECT_HEADER structure were required to make room for this "Lock" field without increasing
the size of the structure.
Instead of pointing directly to the OBJECT_TYPE data structure, the object header now contains an index into a new global data structure nt!ObTypeIndexTable, which is an array of pointers to the different OBJECT_TYPE structures, one of each supported object
type. The following command shows the OBJECT_TYPE structure that a object header would point to if the OBJECT_HEADER->TypeIndex is set to 5 :
describes how to enable various object reference tracing options and view them, in the debugger.
In older versions of Windows, the lower 2 bits (i.e. bits 0 and 1) of the OBJECT_HEADER->QuotaInfoOffset field were used to determine if object reference tracing was enabled on the object. Since the OBJECT_HEADER->QuotaInfoOffset is not longer available
in Windows 7, as discussed later, the new field OBJECT_HEADER->TraceFlag was added to store the object tracing related flags.
been added as shown below:
ObReferenceObjectByHandleWithTag()
ObReferenceObjectByPointerWithTag()
ObReferenceObjectWithTag()
ObDereferenceObjectWithTag()
ObDereferenceObjectDeferDeleteWithTag()
Developers can call these APIs instead of the old ones and pass in a 4 character tag that would be stored along with the stack trace when the operation is performed on the object.
respectively. These xxxInfoOffset fields contain a number (between 0 and 265) that determines the offset of the corresponding OBJECT_HEADER_xxx_INFO structure from the start of the OBJECT_HEADER structure. If any of these fields are zero the object manager
assumes that the corresponding header does not exist. There is another optional header, i.e. OBJECT_HEADER_CREATOR_INFO, whose presence is controlled by a bit in the OBJECT_HEADER->Flag field instead of the xxxInfoOffset fields. The following figure shows
the layout of the optional object headers and their offsets:
Since all of the above optional headers OBJECT_HEADER_NAME_INFO, OBJECT_HEADER_HANDLE_INFO, OBJECT_HEADER_QUOTA_INFO and OBJECT_HEADER_CREATOR_INFO are fixed in size and they are always stored in a specific order, there is little need to store offsets to
these structures. The object manager simply needs to know which ones are present and it can use this information to compute their respective offsets from the start of the OBJECT_HEADER.
So in Windows 7, the 3 xxInfoOffsets fields have been replaced with a single field OBJECT_HEADER->InfoMask, which contains one bit for each optional object header and indicates its presence. In addition to this a new optional header OBJECT_HEADER_PROCESS_INFO
has been introduced in Windows 7. The following table shows the bits in the OBJECT_HEADER->InfoMask, the structures they represent, and the size of these structures that are used to compute the offsets:
The order in which the optional object headers are stored in Windows 7 is shown in the following figure:
Depending on the number and position of the bits set in OBJECT_HEADER->InfoMask a number is calculated which serves as an index into the ObpInfoMaskToOffset[] array. The elements of this array contain the offset of the desired optional header taking into
consideration presence of the other optional headers. This array is large enough to accommodate the offsets for all the 25possibilites based on the bits in OBJECT_HEADER->InfoMask.
The pseudo code for retrieving the offset of the desired optional object header for a particular object is Offset = ObpInfoMaskToOffset[OBJECT_HEADER->InfoMask & (DesiredHeaderBit | (DesiredHeaderBit-1))].
For example, if a certain object has the creator, handle and process info header structures, its OBJECT_HEADER->InfoMask value would be 0x15. If the object manager desires to compute the offset to the handle info header structure for this object, the DesiredHeaderBit
would be 0x04. Based on the above pseudo code, the computed offset to the handle info header structure would be 0x18 as shown by the following command:
When changing the object header in Windows 7 Microsoft ensured that they maintained backward compatibility to the extent that the OBJECT_HEADER size did not change and the OBJECT_HEADER still contained all the information that the previous versions of the
structure did. The document covered the areas of functionality that were affected by the changes to the object header and described the new functionality that was brought about by the changes in the header.
between the legacy and the new object header structures, followed by a detailed description of the reason for the changes and the areas of functionality that are affected by these changes. This document refers to all versions of Windows before Windows 7 as
"older" versions as Windows. All debugger examples used in the document are on Windows Vista SP1 or Windows 7 kernel running on the X86 platform.
A structure becomes an object when the object manager, a component in the Windows kernel, puts headers before the start of the object, to provide a range of services including object naming, object reference counting, checking for security, using information
stored in these headers. The following figure shows the layout of objects and the associated headers:
Figure 1 : Object Layout |
of four different types - details of which are described later.The optional object headers are followed by a mandatory object header which is a structure of type nt!_OBJECT_HEADER and finally the object itself. This could be any of the 37 different object
types supported as of Windows Vista. Examples of objects inlcude events (nt!_KEVENT), semaphores (nt!_KSEMAPHORE), file objects (nt!_FILE_OBJECT), device objects (nt!_DEVICE_OBJECT). The last few bytes of the object header, the field OBJECT_HEADER->Body, overlap
with the actual object body. The OBJECT_HEADER->Type->TypeInfo.PoolType field determines which pool a particular type of objects would be allocated from this can be either PagedPool or NonPagedPool.
OBJECT_HEADER Structure
Running the "!object" command in the kernel debugger displays the following output on older version of Windows:053c: Object: 87d67f80 GrantedAccess: 00000001 Entry: 8fe02a78 Object: 87d67f80 Type: (87515590) File ObjectHeader: 87d67f68 (old version) HandleCount: 1 PointerCount: 1
On Windows 7 and later version of Windows the "!object" command displays a slightly different output:
0328: Object: 84e8ee10 GrantedAccess: 00100001 Entry: 9b710650 Object: 84e8ee10 Type: (848cc3c0) File ObjectHeader: 84e8edf8 (new version) HandleCount: 1 PointerCount: 1
Examining the OBJECT_HEADER structure on the respective versions of Windows shows the reason for the debugger displaying "old version" and "new version". Following debugger output shows the OBJECT_HEADER on older versions of Windows. The fields below that
are highlighted are ones that have been removed from the OBJECT_HEADER structure in Windows 7:
kd> dt nt!_OBJECT_HEADER +0x000 PointerCount : Int4B +0x004 HandleCount : Int4B +0x004 NextToFree : Ptr32 Void +0x008 Type : Ptr32 _OBJECT_TYPE +0x00c NameInfoOffset : UChar +0x00d HandleInfoOffset : UChar +0x00e QuotaInfoOffset : UChar +0x00f Flags : UChar +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION +0x010 QuotaBlockCharged : Ptr32 Void +0x014 SecurityDescriptor : Ptr32 Void +0x018 Body : _QUAD
The highlighted fields below are new to the OBJECT_HEADER structure in Windows 7:
kd> dt nt!_OBJECT_HEADER +0x000 PointerCount : Int4B +0x004 HandleCount : Int4B +0x004 NextToFree : Ptr32 Void +0x008 Lock : _EX_PUSH_LOCK +0x00c TypeIndex : UChar +0x00d TraceFlags : UChar +0x00e InfoMask : UChar +0x00f Flags : UChar +0x010 ObjectCreateInfo : Ptr32 _OBJECT_CREATE_INFORMATION +0x010 QuotaBlockCharged : Ptr32 Void +0x014 SecurityDescriptor : Ptr32 Void +0x018 Body : _QUAD
Per Object Lock
In Windows 7, the new "Lock" field in the OBJECT_HEADER is used to reduce the locking granularity for objects. On older version of Windows, the object manager attempted to acquire an object type specific lock (OBJECT_TYPE->TypeLock) before performing anoperation on an object. This implied that no other object of that type in the entire system could be manipulated for the duration the object type lock was held. With Windows 7, due to the availability of the per-object lock (OBJET_HEADER->Lock), manipulating
one object does not prevent any other object from being manipulated simultaneously, including objects of the same type. The rest of the changes that have been made to the OBJECT_HEADER structure were required to make room for this "Lock" field without increasing
the size of the structure.
Object Type Structure
In older versions of Windows, the OBJECT_HEADER->Type field contained a pointer to the OBJECT_TYPE data structure, which consumed 32/64 bits depending on the platform. In Windows 7, this field has been converted to a CHAR (8-bit) value stored at OBJECT_HEADER->TypeIndex.Instead of pointing directly to the OBJECT_TYPE data structure, the object header now contains an index into a new global data structure nt!ObTypeIndexTable, which is an array of pointers to the different OBJECT_TYPE structures, one of each supported object
type. The following command shows the OBJECT_TYPE structure that a object header would point to if the OBJECT_HEADER->TypeIndex is set to 5 :
kd> dt nt!_OBJECT_TYPE poi(nt!ObTypeIndexTable + ( 5 * @$ptrsize )) +0x000 TypeList : _LIST_ENTRY [ 0x84833960 - 0x84833960 ] +0x008 Name : _UNICODE_STRING "Token" +0x010 DefaultObject : 0x82745ba0 Void +0x014 Index : 0x5 '' +0x018 TotalNumberOfObjects : 0x2f3 +0x01c TotalNumberOfHandles : 0xec +0x020 HighWaterNumberOfObjects : 0x2ff +0x024 HighWaterNumberOfHandles : 0xff +0x028 TypeInfo : _OBJECT_TYPE_INITIALIZER +0x078 TypeLock : _EX_PUSH_LOCK +0x07c Key : 0x656b6f54 +0x080 CallbackList : _LIST_ENTRY [ 0x848339e0 - 0x848339e0 ]
Object Tracing
Object tracing is a new feature added to windows Vista to collect stack traces during object referencing and dereferencing operations. This helps in debugging reference counting problems. The documentation of the "!objtrace" command, in the debugger help,describes how to enable various object reference tracing options and view them, in the debugger.
In older versions of Windows, the lower 2 bits (i.e. bits 0 and 1) of the OBJECT_HEADER->QuotaInfoOffset field were used to determine if object reference tracing was enabled on the object. Since the OBJECT_HEADER->QuotaInfoOffset is not longer available
in Windows 7, as discussed later, the new field OBJECT_HEADER->TraceFlag was added to store the object tracing related flags.
Object Reference Tagging APIs
In Windows 7, the object reference tracing functionality has been enhanced to allow drivers to pass in their own custom tags, to the object referencing and dereferencing APIs. The new "WithTag" versions of all the object reference and dereference APIs havebeen added as shown below:
ObReferenceObjectByHandleWithTag()
ObReferenceObjectByPointerWithTag()
ObReferenceObjectWithTag()
ObDereferenceObjectWithTag()
ObDereferenceObjectDeferDeleteWithTag()
Developers can call these APIs instead of the old ones and pass in a 4 character tag that would be stored along with the stack trace when the operation is performed on the object.
Optional Object Headers
In older versions of Windows, the OBJECT_HEADER structure fields NameInfoOffset, HandleInfoOffset and QuotaInfoOffset were used to describe the presence and location of the optional object headers OBJECT_HEADER_NAME_INFO, OBJECT_HEADER_HANDLE_INFO and OBJECT_HEADER_QUOTA_INFOrespectively. These xxxInfoOffset fields contain a number (between 0 and 265) that determines the offset of the corresponding OBJECT_HEADER_xxx_INFO structure from the start of the OBJECT_HEADER structure. If any of these fields are zero the object manager
assumes that the corresponding header does not exist. There is another optional header, i.e. OBJECT_HEADER_CREATOR_INFO, whose presence is controlled by a bit in the OBJECT_HEADER->Flag field instead of the xxxInfoOffset fields. The following figure shows
the layout of the optional object headers and their offsets:
Figure 2 : Optional Object Headers in older Windows Versions |
these structures. The object manager simply needs to know which ones are present and it can use this information to compute their respective offsets from the start of the OBJECT_HEADER.
So in Windows 7, the 3 xxInfoOffsets fields have been replaced with a single field OBJECT_HEADER->InfoMask, which contains one bit for each optional object header and indicates its presence. In addition to this a new optional header OBJECT_HEADER_PROCESS_INFO
has been introduced in Windows 7. The following table shows the bits in the OBJECT_HEADER->InfoMask, the structures they represent, and the size of these structures that are used to compute the offsets:
Bit | Type | Size (on X86) |
---|---|---|
0x01 | nt!_OBJECT_HEADER_CREATOR_INFO | 0x10 |
0x02 | nt!_OBJECT_HEADER_NAME_INFO | 0x10 |
0x04 | nt!_OBJECT_HEADER_HANDLE_INFO | 0x08 |
0x08 | nt!_OBJECT_HEADER_QUOTA_INFO | 0x10 |
0x10 | nt!_OBJECT_HEADER_PROCESS_INFO | 0x08 |
Figure 3 : Order of Optional Object Headers in Windows 7 |
consideration presence of the other optional headers. This array is large enough to accommodate the offsets for all the 25possibilites based on the bits in OBJECT_HEADER->InfoMask.
The pseudo code for retrieving the offset of the desired optional object header for a particular object is Offset = ObpInfoMaskToOffset[OBJECT_HEADER->InfoMask & (DesiredHeaderBit | (DesiredHeaderBit-1))].
For example, if a certain object has the creator, handle and process info header structures, its OBJECT_HEADER->InfoMask value would be 0x15. If the object manager desires to compute the offset to the handle info header structure for this object, the DesiredHeaderBit
would be 0x04. Based on the above pseudo code, the computed offset to the handle info header structure would be 0x18 as shown by the following command:
kd> ?? ((unsigned char *)@@masm(nt!ObpInfoMaskToOffset))[0x15 & (0x04 | (0x04-1))] unsigned char 0x18 ''
When changing the object header in Windows 7 Microsoft ensured that they maintained backward compatibility to the extent that the OBJECT_HEADER size did not change and the OBJECT_HEADER still contained all the information that the previous versions of the
structure did. The document covered the areas of functionality that were affected by the changes to the object header and described the new functionality that was brought about by the changes in the header.
相关文章推荐
- ios学习路线—Objective-C(ARC)
- 1.多对多双向关联(用户对角色) Object,hbm
- 1.多对多单向关联(用户对角色) Object,hbm
- 【Halcon】获取Hobject的参数[pointer,type,width,height]
- my own objective of keras
- ios学习路线—Objective-C(MRC)
- iOS---Objective-C中@class与#import的区别
- ios学习路线—Objective-C(代码规范)
- @dynamic
- Objective-C中将结构体与联合体封装为NSValue对象
- Object类源码解析
- Android Sharepreference保存Object或者ListObject
- Objective-C图片切圆角优化
- Xcode常用快捷键
- AFNetWorking之GET,POST,上传图片,下载文件进度监测
- 深入浅出Mybatis系列(六)---objectFactory、plugins、mappers简介与配置
- Javascript Object的使用方法 ( 内含遍历Object属性的操作!)
- tsql default values, check current isolation level, check db object last update time
- Training Region-based Object Detectors with Online Hard Example Mining
- ValueAnimator及ObjectAnimator的使用