Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reverse engineer struct details from C source and asm output?

I'm trying to understand the solution to this problem:

Given the C code below, and the asm output from the compiler, what are A and B?

Answer: A is 5, B is 6.

I am guessing there has to be some sort of division done, because 96 and 48 are both divisible by 6 and 20 is divisible by 5.

EDIT: I found this explanation for the answer online. However I am not sure if it is accurate
" a char starts at any BYTE

a short starts only at EVEN bytes

an int starts at BYTE, but divisible by 4

a long starts at BYTE which is divisible by 8

str1.w is long which starts at 5 to 8

str1.x may have 184 or 180

str2.p is int starts at the value 8, hence str1.array which holds from 5 to 8 BYTES

str2.q short may be 14 to 20

str2.z may be 32

char w[A][B] and int X

8 184

Str2.

short[B] int p doublez[B] short q

20 4 8 9

hence the value of A=5 and B=6"

Code below:

// #define A  ??   // 5
// #define B  ??   // 6, but the question is how to figure that out from the asm
typedef struct {
    char w[A][B];
    int x;
} str1;

typedef struct {
    short y[B];
    int p;
    double z[B];
    short q; 
} str2;

void doSub(str1 *t, str2 *u) {
    int v1 = u->p;
    int v2 = u->q;
    t->x = v1-v2;
}

Assembly code generated for doSub procedure:

# t in %rdi, u in %rsi
doSub:
    movswl   96(%rsi), %edx
    movl     20(%rsi), %eax
    subl     %edx, %eax
    movl     %eax, 48(%rdi)
    ret
like image 955
Jaden Avatar asked Nov 18 '25 11:11

Jaden


1 Answers

The assembly code tells you the offsets of the fields used in the C code. So from that, you can tell

offsetof(str1, x) == 48
offsetof(str2, p) == 20
offsetof(str2, q) == 96

Now lets look at p. It comes after y and sizeof(short) is probably 2 (unless this is a pretty unusual machine or compiler), so that tells us B*2 + padding == 20. So B is at most 10, and probably not 8 or less.

Looking at q, sizeof(double) is probably 8 (again, unless unusual), so 20 + sizeof(int) + 8*B + padding == 96. If sizeof(int) == 4 (common, though different sizes for int are more common than for short/double), that gives us 8*B + padding == 72. So B is at most 9. Since short probably has less restrictive alignment than double, there's probably no padding, giving B==9, consistent with 2 bytes of padding before p

Looking at str, sizeof(char) == 1 (always), so A*9 + padding = 48. So the most likely value for A is 5, with 3 bytes of padding.

Of course, the compiler is free to add any padding it wants, so any smaller values for A and B are possible, though wasteful.

like image 200
Chris Dodd Avatar answered Nov 20 '25 02:11

Chris Dodd



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!