Skip to contentSkip to conversation

Offsets from C struct into assembler

Linux-ia64 Christian Hildner 5 participants 8 messages Jan 28, 2002 – Jan 29, 2002

lore
Share & tools
lore
#0 lore raw

Hi!

Does anyone know how to bring offsets from a C structure into pure assembly code (not inline-asm)?
I want to do something like:

struct abc {
    ...
    long varx;
    ...
    }

add rx=offset(varx),ry // get address of variable
ld8 rx=[rx] // get variable varx

with ry being the base address of the structure abc and offset_varx beeing compiled from struct abc.

Any ideas are welcome.

Christian

#1 lore raw
Quoted 10 lines · Christian Hildner

Does anyone know how to bring offsets from a C structure into pure assembly code (not inline-asm)?
I want to do something like:

struct abc {
   ...
   long varx;
   ...
   }
Quoted 5 lines

add rx=offset(varx),ry // get address of variable
ld8 rx=[rx] // get variable varx

with ry being the base address of the structure abc and offset_varx beeing compiled from struct abc.

This is the standard method used by linux kernel build in 2.5 kernels.

== asm-offsets.c

/*
* Generate definitions needed by assembly language modules.
* This code generates raw asm output which is post-processed to extract
* and format the required data.
*/

#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/sched.h>

/* Use marker if you need to separate the values later */

#define DEFINE(sym, val, marker) \
asm volatile("\n-> " #sym " %0 " #val " " #marker : : "i" (val))

#define BLANK() asm volatile("\n->" : : )

int
main(void)
{

  DEFINE(state,        offsetof(struct task_struct, state),);
  DEFINE(flags,        offsetof(struct task_struct, flags),);
  DEFINE(sigpending,   offsetof(struct task_struct, sigpending),);
  DEFINE(addr_limit,   offsetof(struct task_struct, addr_limit),);
  DEFINE(exec_domain,  offsetof(struct task_struct, exec_domain),);

DEFINE(need_resched, offsetof(struct task_struct, need_resched),);
DEFINE(tsk_ptrace, offsetof(struct task_struct, ptrace),);
DEFINE(processor, offsetof(struct task_struct, processor),);
BLANK();
DEFINE(ENOSYS, ENOSYS,);
return 0;
}

== Compile 'gcc asm-offsets.c -S -o asm-offsets.s' then

# Convert raw asm offsets into something that can be included as

# assembler definitions.  It converts
#   -> symbol $value source
# into
#   #define symbol value /* 0xvalue source */
	(set -e;
	  (echo "#ifndef __ASM_OFFSETS_H__";
	   echo "#define __ASM_OFFSETS_H__";
	   echo "/*";
	   echo " * DO NOT MODIFY";
	   echo " *";
	   echo " * This file was generated by arch/${ARCH}/Makefile.in.";
	   echo " *";
	   echo " */";
	   echo "";
	   awk "/^->\$/{printf(\"\\n\");}
	     /^-> /{
	       sym = \$2;
	       val = \$3;
	       sub(/^\\\$/, \"\", val);
	       \$1 = \"\";
	       \$2 = \"\";
	       \$3 = \"\";
	       printf(\"#define %-40s %5d\\t\\t\\t/* 0x%x\\t%s */\\n\",
	         sym, val, val, \$0)
	     }";
	   echo "";
	   echo "#endif";
	  ) < asm-offsets.s > asm-offsets.h)

asm-offsets.h contains #define statements for each DEFINE in asm-offsets.c.

#2 lore raw
In reply to Christian Hildner

Or you can check out how the IA64 Linux kernel does this. The file arch/ia64/tools/printoffsets.c' is a program that is compiled and, when run, generates the file include asm-ia64/offsets.h' which is an ASM include file containing structure offsets.

Quoted 96 lines · Keith Owens
Quoted 10 lines · Christian Hildner

Does anyone know how to bring offsets from a C structure into pure assembly code (not inline-asm)?
I want to do something like:

struct abc {
   ...
   long varx;
   ...
   }
Quoted 5 lines

add rx=offset(varx),ry // get address of variable
ld8 rx=[rx] // get variable varx

with ry being the base address of the structure abc and offset_varx beeing compiled from struct abc.

This is the standard method used by linux kernel build in 2.5 kernels.

== asm-offsets.c

/*
* Generate definitions needed by assembly language modules.
* This code generates raw asm output which is post-processed to extract
* and format the required data.
*/

#include <linux/types.h>
#include <linux/stddef.h>
#include <linux/sched.h>

/* Use marker if you need to separate the values later */

#define DEFINE(sym, val, marker) \
asm volatile("\n-> " #sym " %0 " #val " " #marker : : "i" (val))

#define BLANK() asm volatile("\n->" : : )

int
main(void)
{

  DEFINE(state,        offsetof(struct task_struct, state),);
  DEFINE(flags,        offsetof(struct task_struct, flags),);
  DEFINE(sigpending,   offsetof(struct task_struct, sigpending),);
  DEFINE(addr_limit,   offsetof(struct task_struct, addr_limit),);
  DEFINE(exec_domain,  offsetof(struct task_struct, exec_domain),);

DEFINE(need_resched, offsetof(struct task_struct, need_resched),);
DEFINE(tsk_ptrace, offsetof(struct task_struct, ptrace),);
DEFINE(processor, offsetof(struct task_struct, processor),);
BLANK();
DEFINE(ENOSYS, ENOSYS,);
return 0;
}

== Compile 'gcc asm-offsets.c -S -o asm-offsets.s' then

# Convert raw asm offsets into something that can be included as

# assembler definitions.  It converts
#   -> symbol $value source
# into
#   #define symbol value /* 0xvalue source */
	(set -e;
	  (echo "#ifndef __ASM_OFFSETS_H__";
	   echo "#define __ASM_OFFSETS_H__";
	   echo "/*";
	   echo " * DO NOT MODIFY";
	   echo " *";
	   echo " * This file was generated by arch/${ARCH}/Makefile.in.";
	   echo " *";
	   echo " */";
	   echo "";
	   awk "/^->\$/{printf(\"\\n\");}
	     /^-> /{
	       sym = \$2;
	       val = \$3;
	       sub(/^\\\$/, \"\", val);
	       \$1 = \"\";
	       \$2 = \"\";
	       \$3 = \"\";
	       printf(\"#define %-40s %5d\\t\\t\\t/* 0x%x\\t%s */\\n\",
	         sym, val, val, \$0)
	     }";
	   echo "";
	   echo "#endif";
	  ) < asm-offsets.s > asm-offsets.h)

asm-offsets.h contains #define statements for each DEFINE in asm-offsets.c.

_______________________________________________
Linux-IA64 mailing list
[email protected]
http://lists.linuxia64.org/lists/listinfo/linux-ia64

Signature · 4 lines
Don Dugger
"Censeo Toto nos in Kansa esse decisse." - D. Gale
[email protected]
Ph: 303/652-0870x117
#3 lore raw
In reply to Christian Hildner
Quoted 4 lines · On Mon, 28 Jan 2002 08:11:23 -0700, [email protected] wrote:

Or you can check out how the IA64 Linux kernel does this. The file arch/ia64/tools/printoffsets.c' is a program that is compiled and, when run, generates the file include asm-ia64/offsets.h' which is an ASM include file containing structure offsets.

That tool is disappearing in 2.5 kernels. All architectures will use the same method for generating asm offsets, the one I included in my previous mail.

#4 lore raw
In reply to Christian Hildner
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Keith Owens

Keith> On Mon, 28 Jan 2002 08:11:23 -0700, [email protected]

Quoted 5 lines · Keith> wrote:
Quoted 5 lines

Or you can check out how the IA64 Linux kernel does this. The file arch/ia64/tools/printoffsets.c' is a program that is compiled and, when run, generates the file include asm-ia64/offsets.h' which is an ASM include file containing structure offsets.

Keith> That tool is disappearing in 2.5 kernels. All architectures Keith> will use the same method for generating asm offsets, the one Keith> I included in my previous mail.

As of v2.5.3-pre5 I don't see any sign of your new kernel build environment being part of Linus' tree. Perhaps it will be accepted some day, but until that happens, the scheme described by Don is the correct one.

	--david
#5 lore raw
In reply to Christian Hildner
Quoted 14 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Keith Owens

Keith> On Mon, 28 Jan 2002 08:11:23 -0700, [email protected]

Quoted 5 lines · Keith> wrote:
Quoted 5 lines

Or you can check out how the IA64 Linux kernel does this. The file arch/ia64/tools/printoffsets.c' is a program that is compiled and, when run, generates the file include asm-ia64/offsets.h' which is an ASM include file containing structure offsets.

Keith> That tool is disappearing in 2.5 kernels. All architectures Keith> will use the same method for generating asm offsets, the one Keith> I included in my previous mail.

Quoted 6 lines

As of v2.5.3-pre5 I don't see any sign of your new kernel build environment being part of Linus' tree. Perhaps it will be accepted some day, but until that happens, the scheme described by Don is the correct one.

        --david

Although it would be a nice feature of the gcc if it could include C headers combined with an assembler directive for using the offsets the simple solution with print_offsets does it's job fine. The good thing here is that awk isn't needed.

Thanks,

Christian

#6 lore raw
In reply to Christian Hildner
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Christian Hildner

Christian> Although it would be a nice feature of the gcc if it Christian> could include C headers combined with an assembler Christian> directive for using the offsets the simple solution with Christian> print_offsets does it's job fine. The good thing here is Christian> that awk isn't needed.

It's not difficult to fix print_offsets.c to avoid awk. We could use directives of the form:

  asm volatile ("uc_rnat = %0"::"i"(offsetof (struct _Unwind_Context, rnat)));

for this purpose (this is a cut & paste from gcc's unwind-ia64.c).

	--david
#7 lore raw
In reply to Christian Hildner

David Mosberger <[email protected]> writes:

|> >>>>> On Tue, 29 Jan 2002 08:06:46 +0100, Christian Hildner <[email protected]> said:
|> 
|>   Christian> Although it would be a nice feature of the gcc if it
|>   Christian> could include C headers combined with an assembler
|>   Christian> directive for using the offsets the simple solution with
|>   Christian> print_offsets does it's job fine. The good thing here is
|>   Christian> that awk isn't needed.
|> 
|> It's not difficult to fix print_offsets.c to avoid awk.  We could use
|> directives of the form:
|> 
|>   asm volatile ("uc_rnat = %0"::"i"(offsetof (struct _Unwind_Context, rnat)));
|> 
|> for this purpose (this is a cut & paste from gcc's unwind-ia64.c).

You still have to post-process the output to make it usefull for the assembler.

Andreas.

Signature · 4 lines
Andreas Schwab, SuSE Labs, [email protected]
SuSE GmbH, Deutschherrnstr. 15-19, D-90429 Nürnberg
Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."