From owner-freebsd-current Sun Jul 14 13:36:18 2002 Delivered-To: freebsd-current@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E0D8F37B401 for ; Sun, 14 Jul 2002 13:36:14 -0700 (PDT) Received: from mail.gmx.net (mail.gmx.net [213.165.64.20]) by mx1.FreeBSD.org (Postfix) with SMTP id 54DCD43E31 for ; Sun, 14 Jul 2002 13:36:13 -0700 (PDT) (envelope-from tmoestl@gmx.net) Received: (qmail 18427 invoked by uid 0); 14 Jul 2002 20:36:01 -0000 Received: from pd953895d.dip.t-dialin.net (HELO forge.local) (217.83.137.93) by mail.gmx.net (mp014-rz3) with SMTP; 14 Jul 2002 20:36:01 -0000 Received: from tmm by forge.local with local (Exim 3.36 #1) id 17Tq6k-0001aB-00; Sun, 14 Jul 2002 22:36:42 +0200 Date: Sun, 14 Jul 2002 22:36:42 +0200 From: Thomas Moestl To: Luigi Rizzo Cc: current@freebsd.org Subject: Re: different packing of structs in kernel vs. userland ? Message-ID: <20020714203642.GD314@crow.dom2ip.de> Mail-Followup-To: Luigi Rizzo , current@freebsd.org References: <20020714011810.A72236@iguana.icir.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20020714011810.A72236@iguana.icir.org> User-Agent: Mutt/1.4i Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG On Sun, 2002/07/14 at 01:18:10 -0700, Luigi Rizzo wrote: > Hi, > the following message seems to suggest that the compiler > (the way it is invoked) packs structures differently > when building the kernel and userland. > > The stize of the structure in question is computed > by both kernel and userland app using sizeof(), > so there is no assumption on the size of its members, > so i believe the only possibility of a mismatch is > the one above. > > Any ideas ? (Disclaimer: my solution below is untested, so it may all be bogus) No, you are not accounting for "external" structure padding. Take a look: struct ip_fw { struct ip_fw *next; /* linked list of rules */ u_int16_t act_ofs; /* offset of action in 32-bit units */ u_int16_t cmd_len; /* # of 32-bit words in cmd */ u_int16_t rulenum; /* rule number */ u_int16_t _pad; /* padding */ /* These fields are present in all rules. */ u_int64_t pcnt; /* Packet counter */ u_int64_t bcnt; /* Byte counter */ u_int32_t timestamp; /* tv_sec of last match */ struct ip_fw *next_rule; /* ptr to next rule */ ipfw_insn cmd[1]; /* storage for commands */ }; On a 64-bit architecture, pointers are obviously 8 bytes in size; structure members must or should be on natural borders, depending on the architecture. So, next_rule will not be on a natural border; 4 bytes of padding will be inserted before it. With that, the total structure size would be 52. The compiler must account for the fact that an array of struct ip_fws may be used. For obvious reasons, it can not just insert extra padding in the array case; instead, the structure size must be chosen so that in this situation, the first member will be on a natural border. This results in an extra 4 bytes of "external" padding at the end, after the member 'cmd'. The macro you use to compute the size in the kernel is: #define RULESIZE(rule) (sizeof(struct ip_fw) + \ ((struct ip_fw *)(rule))->cmd_len * 4 - 4) In the userland code, you start at &foo.cmd and append data directly. This means that the padding will also be used to store data, so the '- 4' (= sizeof(foo.cmd)) will not always be enough. The following definition of RULESIZE (untested) should fix this: #define RULESIZE(rule) (offsetof(struct ip_fw, cmd) + \ ((struct ip_fw *)(rule))->cmd_len * 4) It also removes the explicit 4 for sizeof(ipfw_insn). - thomas -- Thomas Moestl http://www.tu-bs.de/~y0015675/ http://people.FreeBSD.org/~tmm/ PGP fingerprint: 1C97 A604 2BD0 E492 51D0 9C0F 1FE6 4F1D 419C 776C To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message