从编译器asm输出反向工程数组尺寸/结构布局? [英] Reverse engineer array dimensions / struct layout from compiler asm output?

查看:89
本文介绍了从编译器asm输出反向工程数组尺寸/结构布局?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在此代码中,A和B是用#define定义的常量. A和B的值是什么?

In this code, A and B are constants defined with #define. What are the values of A and B?

typedef struct {
    int x[A][B];
    long y;
} str1;

typedef struct {
    char array[B];
    int t;
    short S[A];
    long u;
} str2;

void setVal(str1 *p, str2 *q) {
    long v1 = q->t;
    long v2 = q->u;
    p->y = v1+v2;
}

setVal过程生成以下汇编代码:

The following assembly code is generated for the setVal procedure:

setVal:
    movslq  8(%rsi), %rax
    addq   32(%rsi), %rax
    movq     %rax, 184(%rdi)
    ret

推荐答案

结构具有以下对齐要求:

The structure has the following alignment requirements:

  • char可以从任何字节开始
  • short可能以偶数字节开头
  • int可以从字节开始,可以被四整除
  • long可以从字节开始,可以被8整除
  • a char may start at any byte
  • a short may start at even byte
  • an int may start at byte, divisible by four
  • a long may start at byte, divisible by eight

str1.y字段是long,从184开始,这意味着str1.x可以容纳184180字节.

The str1.y field is a long and starts at 184, this implies, that str1.x may hold either 184 or 180 bytes.

str2.t字段是一个int,并从8开始,这意味着str1.array可以容纳58个字节.

The str2.t field is an int and starts at 8, this implies, that str1.array may hold from 5 to 8 bytes.

str2.u字段是long,起始于32,这意味着str2.S的字节数可能从1420.

The str2.u field is a long and starts at 32, this implies, that str2.S may hold from 14 to 20 bytes.

这是str1结构字段的图:

+---------------+---+--------+
|  int x[A][B]  | ? | long y |
+---------------+---+--------+
|        184        |    8   |
+-------------------+--------+

这是str2字段的示意图:

+---------------+---+-------+------------+---+--------+
| char array[B] | ? | int t | short S[A] | ? | long u |
+---------------+---+-------+------------+---+--------+
|         8         |   4   |        20      |    8   |
+-------------------+-------+----------------+--------+

在那之后,您应该解决以下系统:

After that, you should solve the following system:

177 <= 4 * A * B <= 184
5 <= B <= 8
14 <= A * 2 <= 20      // 7 <= A <= 10

答案是:A = 9B = 5

您可以使用编译器来测试您的答案(以及每个不等式的范围),该编译器遵循产生原始代码的编译器所使用的相同ABI/调用约定.它使用8字节long:请注意addq(而不是addl)的64位操作数大小和8字节存储.因此,我们可以推断出它很可能是x86-64 System V ABI,而不是Windows x86-64调用约定(使用4字节long).

You can test your answer (and the ranges for each inequality) using a compiler that follows the same ABI / calling convention used by the compiler that produced the original code. It uses 8-byte long: note the 64-bit operand size for the addq, instead of addl, and the 8-byte store. Thus, we can infer that it's most likely the x86-64 System V ABI, not the Windows x86-64 calling convention (which uses 4-byte long).

Godbolt编译器浏览器具有gcc,clang,ICC和MSVC.前三个以Linux为目标,但MSVC以Windows调用约定为目标,因此对于较小的long需要较少对齐的结构布局,就不会达成共识.

The Godbolt compiler explorer has gcc, clang, ICC, and MSVC. The first 3 target Linux, but MSVC targets the Windows calling convention and thus won't agree on struct layout with a smaller long requiring less alignment.

Replacing int x[A][B] with char t[177] (or other sizes) proves that 177 is the minimum and 184 is the maximum size that that leads to a store to 184(%rdi). So we could have written 176 < 4*A*B <= 184. Or, to keep things to multiples of 4, 180 <= 4*A*B <= 184 is also more or less correct; we can rule out 177..179 based on the size of int.

这篇关于从编译器asm输出反向工程数组尺寸/结构布局?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆