9

For example, how to prepare parameters for this syscall sys_wait4:

 asmlinkage long sys_wait4(pid_t pid,unsigned int __user *stat_addr, int options, struct rusage __user *ru)
1120 {

How to deal with struct rusage in assembly?

A hello world example to deal with struct in assembly is enough for me:)

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
R__
  • 1,441
  • 5
  • 16
  • 22

1 Answers1

17

The members of a struct are laid out sequentially in memory, possibly with padding, and the address of the struct is typically the address of its first member.

struct Bar {
    int x;
    int y;
};

struct Foo {
    struct Bar b;
    double d;
    int i;
};

struct Foo f;

Let's say that &f is 0x10. Then, &f.b.x (the first member of the first member of Foo) is also 0x10. &f.b.y is 0x14, since f.b.x is four bytes (assuming a 32-bit machine). &f.d is 0x18, and &f.i is 0x20. The first address that is not occupied by f (in other words, &f + 1) is 0x24.

So all you need to do in assembly is to make sure that you have (stack or heap) space for the members of the struct, and fill the space with appropriate data, and pass the address of the first member to the function.

As for an example that actually involves assembly, you could easily produce that yourself by writing a small test program and compile it with gcc -S -O0 -g, which will produce assembly code for your C code. For example:

int func(struct Foo * foo) {
    return foo->b.x + foo->i;
}

int main() {
    struct Foo foo;
    foo.b.x = 42;
    foo.b.y = 9;
    foo.d = 3.14;
    foo.i = 8;
    func(&foo);
    return 0;
}

In the assembly output, you will, among other things, see (note: this is 64-bit ASM):

movl    $42, -32(%rbp)
movl    $9, -28(%rbp)
movabsq $4614253070214989087, %rax
movq    %rax, -24(%rbp)
movl    $8, -16(%rbp)

As you can see, the values 42, 9, (integer whose bit pattern is that of 3.14), and 8 being loaded into the addresses -32, -28, -24, and -16 (relative to the base pointer). I only have a Solaris box handy, so I couldn't use asmlinkage (which specifies that the function arguments must be passed on the stack rather than in the registers), so immediately before the function call, we see the effective address of the struct being loaded into a register:

leaq    -32(%rbp), %rax
movq    %rax, %rdi

With asmlinkage, you'd instead see this effective address being pushed onto the stack.

Aasmund Eldhuset
  • 37,289
  • 4
  • 68
  • 81
  • Eldhuset,a hello world example available? – R__ Jul 01 '11 at 15:14
  • 2
    I think C99 guarantees that the address of a struct is the address of its first member. – tc. Jul 02 '11 at 01:31
  • @tc.: Sounds reasonable; I wrote "typically" just because I wasn't 100% sure that that was the case - but I can't see any reason why one would want to add padding at the start of a struct. – Aasmund Eldhuset Jul 02 '11 at 01:34
  • I believe C99 additionally makes it safe to cast between pointers to structs that start with the same fields and access those fields (so you can cast `struct sockaddr_in*` to `struct sockaddr*`). There's a similar guarantee which means you can use `offsetof()`. – tc. Jul 02 '11 at 01:43
  • 2
    @R__: You can produce one yourself by asking the compiler to output assembly. See my updated answer. – Aasmund Eldhuset Jul 02 '11 at 11:27