在对齐之前获取实际结构大小

发布于 2025-02-12 00:53:38 字数 577 浏览 3 评论 0 原文

因此,事实证明, dt struct ? sizeof struct 返回对齐后结构在内存中占据的总尺寸。

有没有办法在对齐之前获取结构的实际尺寸?

我需要此功能,用于返回结构内字段的实际大小的函数。例如:

__declspec(align(64)) struct ALIGNED_STRUCT {
    char field;
}

运行 ?? sizeof(aligned_struct)应该获得0x40,这使得很难推断出内部字段的实际大小。

编辑:

命令输出:

2:001> dt -v ALIGNED_STRUCT 
test!ALIGNED_STRUCT 
struct ALIGNED_STRUCT, 1 elements, 0x40 bytes
   +0x000 field            : Char

3:001> ?? sizeof(ALIGNED_STRUCT)
0x40 

So it turns out that both dt struct and ?? sizeof struct return the total size the struct occupies in memory after alignment.

Is there a way to get the actual size of the struct before alignment?

I need this functionality for a function that returns the actual size of a field within a struct. For example:

__declspec(align(64)) struct ALIGNED_STRUCT {
    char field;
}

running ?? sizeof(ALIGNED_STRUCT) one should get 0x40 which makes it hard to deduce the actual size of the internal field.

edit:

command outputs:

2:001> dt -v ALIGNED_STRUCT 
test!ALIGNED_STRUCT 
struct ALIGNED_STRUCT, 1 elements, 0x40 bytes
   +0x000 field            : Char

3:001> ?? sizeof(ALIGNED_STRUCT)
0x40 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

惜醉颜 2025-02-19 00:53:38

不 - 没有办法返回“对齐前”结构大小。无论如何,这并不是真正有意义的。编译器始终使用对齐尺寸。符号具有对齐的大小。那就是类型的大小。

如果您正在寻找诸如“内部字段的大小”之类的东西,那么有很多方法可以实现这一目标。如评论中所述,您可以执行快速的肮脏ee sizeof操作:

    dx sizeof(((ALIGNED_STRUCT *)0)->field)

您也可以通过数据模型API(在A C/C ++扩展名或JavaScript中)获得完整访问对基础类型的系统进行)这将使您几乎可以找到有关类型的任何内容:它们的字段,尺寸,偏移,功能参数类型,模板参数等...

从C/C ++,您可以:

通过调用可能看起来像 之类的

ComPtr<IDebugHostSymbols> spHostSymbols;  /* QI this off IDebugClient, etc... */
ComPtr<IDebugHostModule> spMyModule;
if (FAILED(spHostSymbols->FindModuleByName(USE_CURRENT_HOST_CONTEXT, L"myModule", &spMyModule)))
{
    return ...;
}

ComPtr<IDebugHostType> spType;
if (FAILED(spMyModule->FindTypeByName(L"ALIGNED_STRUCT", &spType)))
{
    return ...;
}

ComPtr<IDebugHostType> spType; /* get the type of an object */

//
// Enumerate every field of this type.  Note thiat this *WILL NOT* enumerate 
// fields of base classes!
//
ComPtr<IDebugHostSymbolEnumerator> spEnum;
if (SUCCEEDED(spType->EnumerateChildren(SymbolField, nullptr, &spEnum)))
{
    ComPtr<IDebugHostSymbol> spFieldSymbol;
    HRESULT hr = S_OK;
    while (SUCCEEDED(hr))
    {
        hr = spEnum->GetNext(&spFieldSymbol);
        if (SUCCEEDED(hr))
        {
            ComPtr<IDebugHostField> spField;
            if (SUCCEEDED(spFieldSymbol.As(&spField))) /* should always succeed */
            {
                // spField is each field of the type in turn
            }

            ULONG64 fieldOffset;
            if (SUCCEEDED(spField->GetOffset(&fieldOffset)) /* won't succeed on static fields */
            {
                // fieldOffset is the offset of the field within the type
            }

            ComPtr<IDebugHostType> spFieldType;
            if (SUCCEEDED(spField->GetType(&spFieldType))
            {
                ULONG64 fieldSize;
                if (SUCCEEDED(spFieldType->GetSize(&fieldSize)))
                {
                    // fieldSize contains the size (aligned) of the field's type
                }
            }
        }
    }

    // hr == E_BOUNDS : we hit the end of the enumerator
    // hr == E_ABORT  : user requested interruption, propagate upwards immediately
}

:对于C ++,可以通过使用该<> 来更轻松地使其更容易。 C ++ 17助手库(

Module myModule(HostContext::DeferredCurrent(), L"myModule");
Type alignedStruct(myModule, L"ALIGNED_STRUCT");

//
// The below will *NOT* enumerate fields of base classes.  You must explicitly
// recurse if you want such.
//
for(Field f : alignedStruct.Fields())
{
    //
    // Get the offset and size of each field. 
    //
    ULONG64 fieldOffset = f.GetOffset();
    ULONG64 fieldSize = f.Type().Size();
}

​.microsoft.com/en-us/windows-hardware/drivers/debugger/natiber-objects-in-javascript-extensions-extensions-type-objects“ rel =” nofollow noreferrer“> https://learn.microsoft.com/microsoft.com/en--en--- US/Windows-Hardware/drivers/debugger/native-objects-in-javascript-extensions-type-objects ),这看起来像:

  • call host.getModuletype 获取类型对象对于结构(例如:aligned_struct),
  • 访问有关字段。
  • 通过访问类型上的 fields 的命名属性(例如:mytype.fields.fields.field_name)来 offset 属性
  • 通过访问 type 属性来获取每个字段的类型
  • size size 属性

,通过访问 可能看起来

var myType = host.getModuleType("myModule", "ALIGNED_STRUCT");
var fields = myType.fields;

//
// In JavaScript, fields has properties named according to each field.  If
// you want to enumerate, get the property names and access those keys.
//
var fieldNames = Object.getOwnPropertyNames(fields);
for (var fieldName of fieldNames)
{
    var field = fields[fieldName];
    
    //
    // Get the offset and size of each field...
    //
    var fieldOffset = field.offset;
    var fieldSize = field.type.size;
}

在任何一种情况下,如果您要查看基本类中包含字段的C ++对象,则需要手动重复基础类。

希望有帮助...

No -- there isn't a way to return the structure size "before alignment". That's not really meaningful in any case. The compiler is always using the aligned size. The symbols have the aligned size. That's the size of the type.

If you are looking for things like the "size of an internal field", there are numerous ways to accomplish this. As mentioned in comments, you can do the quick dirty EE sizeof thing:

    dx sizeof(((ALIGNED_STRUCT *)0)->field)

You can also get full access to the underlying type system via the data model APIs (in either a C/C++ extension or in JavaScript) which will allow you to find out pretty much whatever you want about the types: their fields, sizes, offsets, function parameter types, template arguments, etc...

From C/C++, you can:

That might look something like this:

ComPtr<IDebugHostSymbols> spHostSymbols;  /* QI this off IDebugClient, etc... */
ComPtr<IDebugHostModule> spMyModule;
if (FAILED(spHostSymbols->FindModuleByName(USE_CURRENT_HOST_CONTEXT, L"myModule", &spMyModule)))
{
    return ...;
}

ComPtr<IDebugHostType> spType;
if (FAILED(spMyModule->FindTypeByName(L"ALIGNED_STRUCT", &spType)))
{
    return ...;
}

ComPtr<IDebugHostType> spType; /* get the type of an object */

//
// Enumerate every field of this type.  Note thiat this *WILL NOT* enumerate 
// fields of base classes!
//
ComPtr<IDebugHostSymbolEnumerator> spEnum;
if (SUCCEEDED(spType->EnumerateChildren(SymbolField, nullptr, &spEnum)))
{
    ComPtr<IDebugHostSymbol> spFieldSymbol;
    HRESULT hr = S_OK;
    while (SUCCEEDED(hr))
    {
        hr = spEnum->GetNext(&spFieldSymbol);
        if (SUCCEEDED(hr))
        {
            ComPtr<IDebugHostField> spField;
            if (SUCCEEDED(spFieldSymbol.As(&spField))) /* should always succeed */
            {
                // spField is each field of the type in turn
            }

            ULONG64 fieldOffset;
            if (SUCCEEDED(spField->GetOffset(&fieldOffset)) /* won't succeed on static fields */
            {
                // fieldOffset is the offset of the field within the type
            }

            ComPtr<IDebugHostType> spFieldType;
            if (SUCCEEDED(spField->GetType(&spFieldType))
            {
                ULONG64 fieldSize;
                if (SUCCEEDED(spFieldType->GetSize(&fieldSize)))
                {
                    // fieldSize contains the size (aligned) of the field's type
                }
            }
        }
    }

    // hr == E_BOUNDS : we hit the end of the enumerator
    // hr == E_ABORT  : user requested interruption, propagate upwards immediately
}

For C++, this can be made significantly easier by using the C++17 helper library on GitHub (https://github.com/microsoft/WinDbg-Libraries/blob/master/DbgModelCppLib/DbgModelClientEx.h)

That might look something like:

Module myModule(HostContext::DeferredCurrent(), L"myModule");
Type alignedStruct(myModule, L"ALIGNED_STRUCT");

//
// The below will *NOT* enumerate fields of base classes.  You must explicitly
// recurse if you want such.
//
for(Field f : alignedStruct.Fields())
{
    //
    // Get the offset and size of each field. 
    //
    ULONG64 fieldOffset = f.GetOffset();
    ULONG64 fieldSize = f.Type().Size();
}

In JavaScript (see https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/native-objects-in-javascript-extensions-type-objects), this would look like:

  • Call host.getModuleType to get a type object for the structure (e.g.: ALIGNED_STRUCT)
  • Get access to the field in question by accessing the named property of fields on the type (e.g.: myType.fields.field_name)
  • Get the offset of of such field by accessing the offset property
  • Get the type of each field by accessing the type property
  • Get the size of the field by accessing the size property of its type

That might look something like:

var myType = host.getModuleType("myModule", "ALIGNED_STRUCT");
var fields = myType.fields;

//
// In JavaScript, fields has properties named according to each field.  If
// you want to enumerate, get the property names and access those keys.
//
var fieldNames = Object.getOwnPropertyNames(fields);
for (var fieldName of fieldNames)
{
    var field = fields[fieldName];
    
    //
    // Get the offset and size of each field...
    //
    var fieldOffset = field.offset;
    var fieldSize = field.type.size;
}

In either of these cases, you would need to manually recurse base classes if you're looking at C++ objects where fields are contained in base classes.

Hope that helps...

时光倒影 2025-02-19 00:53:38

威廉提供了一个全面的答案,这个答案只是一个实用的例子

0:000> dx @$stru
@$stru           : Pcb _KPROCESS (+ 0x0)
    name             : Pcb
    type             : _KPROCESS
    locationKind     : member
    offset           : 0x0
0:000> dx @$stru.type.fields.Header.type.size
@$stru.type.fields.Header.type.size : 0x18
0:000>

William has provided a comprehensive answer this answer is just a practical example of that

0:000> dx @$stru
@$stru           : Pcb _KPROCESS (+ 0x0)
    name             : Pcb
    type             : _KPROCESS
    locationKind     : member
    offset           : 0x0
0:000> dx @$stru.type.fields.Header.type.size
@$stru.type.fields.Header.type.size : 0x18
0:000>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文