]> git.ipfire.org Git - thirdparty/iw.git/commitdiff
iw: change __cmd section scheme to fit gcc/clang
authorJohannes Berg <johannes.berg@intel.com>
Thu, 2 May 2019 08:05:47 +0000 (10:05 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 2 May 2019 08:05:47 +0000 (10:05 +0200)
There are some behaviour differences in how gcc and clang
fill a special section like the one we use for __cmd here.

In both compilers, obviously all variables declared like
this end up in the special __cmd section.

However, alignment and padding is applied differently by
different compilers and linkers, and as such it is hard to
really rely on being able to treat this like an array.

To avoid all these issues, put just *pointers* to the
structures into the special section, which makes it easy
to skip NULL pointers (resulting from padding) and has no
issues with alignment as they're always smaller than the
alignment applied.

Change-Id: I35e2c66e541758e60363883d26b31d2040ce8aa9
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
iw.c
iw.h

diff --git a/iw.c b/iw.c
index 40f8f6ea7d69ca2c92449de533cf1872cd15bb5b..da71617921d8a3c0a8e7c8c05f4e76dcba4987c0 100644 (file)
--- a/iw.c
+++ b/iw.c
@@ -89,12 +89,12 @@ static void nl80211_cleanup(struct nl80211_state *state)
 
 static int cmd_size;
 
-extern struct cmd __start___cmd;
-extern struct cmd __stop___cmd;
+extern struct cmd *__start___cmd[];
+extern struct cmd *__stop___cmd;
 
-#define for_each_cmd(_cmd)                                     \
-       for (_cmd = &__start___cmd; _cmd < &__stop___cmd;               \
-            _cmd = (const struct cmd *)((char *)_cmd + cmd_size))
+#define for_each_cmd(_cmd, i)                                  \
+       for (i = 0; i < &__stop___cmd - __start___cmd; i++)     \
+               if ((_cmd = __start___cmd[i]))
 
 
 static void __usage_cmd(const struct cmd *cmd, char *indent, bool full)
@@ -192,6 +192,7 @@ static void usage(int argc, char **argv)
        bool full = argc >= 0;
        const char *sect_filt = NULL;
        const char *cmd_filt = NULL;
+       unsigned int i, j;
 
        if (argc > 0)
                sect_filt = argv[0];
@@ -203,7 +204,7 @@ static void usage(int argc, char **argv)
        usage_options();
        printf("\t--version\tshow version (%s)\n", iw_version);
        printf("Commands:\n");
-       for_each_cmd(section) {
+       for_each_cmd(section, i) {
                if (section->parent)
                        continue;
 
@@ -213,7 +214,7 @@ static void usage(int argc, char **argv)
                if (section->handler && !section->hidden)
                        __usage_cmd(section, "\t", full);
 
-               for_each_cmd(cmd) {
+               for_each_cmd(cmd, j) {
                        if (section != cmd->parent)
                                continue;
                        if (!cmd->handler || cmd->hidden)
@@ -350,7 +351,7 @@ static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
        struct nl_cb *s_cb;
        struct nl_msg *msg;
        signed long long devidx = 0;
-       int err, o_argc;
+       int err, o_argc, i;
        const char *command, *section;
        char *tmp, **o_argv;
        enum command_identify_by command_idby = CIB_NONE;
@@ -402,7 +403,7 @@ static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
        argc--;
        argv++;
 
-       for_each_cmd(sectcmd) {
+       for_each_cmd(sectcmd, i) {
                if (sectcmd->parent)
                        continue;
                /* ok ... bit of a hack for the dupe 'info' section */
@@ -420,7 +421,7 @@ static int __handle_cmd(struct nl80211_state *state, enum id_input idby,
        if (argc > 0) {
                command = *argv;
 
-               for_each_cmd(cmd) {
+               for_each_cmd(cmd, i) {
                        if (!cmd->handler)
                                continue;
                        if (cmd->parent != sectcmd)
diff --git a/iw.h b/iw.h
index 16ff0765307ea3d46114e4f9939d7e716cb61f18..ca8a0ff1ae185b6f69c2b9559109b87049b46d4e 100644 (file)
--- a/iw.h
+++ b/iw.h
@@ -106,8 +106,7 @@ struct chandef {
 
 #define __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel)\
        static struct cmd                                               \
-       __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden\
-       __attribute__((used)) __attribute__((section("__cmd"))) = {     \
+       __cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden = {\
                .name = (_name),                                        \
                .args = (_args),                                        \
                .cmd = (_nlcmd),                                        \
@@ -118,7 +117,10 @@ struct chandef {
                .help = (_help),                                        \
                .parent = _section,                                     \
                .selector = (_sel),                                     \
-       }
+       };                                                              \
+       static struct cmd *__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden ## _p \
+       __attribute__((used,section("__cmd"))) =                        \
+       &__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden
 #define __ACMD(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel, _alias)\
        __COMMAND(_section, _symname, _name, _args, _nlcmd, _flags, _hidden, _idby, _handler, _help, _sel);\
        static const struct cmd *_alias = &__cmd ## _ ## _symname ## _ ## _handler ## _ ## _nlcmd ## _ ## _idby ## _ ## _hidden
@@ -130,10 +132,7 @@ struct chandef {
        __COMMAND(&(__section ## _ ## section), name, #name, args, cmd, flags, 1, idby, handler, NULL, NULL)
 
 #define TOPLEVEL(_name, _args, _nlcmd, _flags, _idby, _handler, _help) \
-       extern struct cmd __section ## _ ## _name; /* sparse */         \
-       struct cmd                                                      \
-       __section ## _ ## _name                                         \
-       __attribute__((used)) __attribute__((section("__cmd"))) = {     \
+       struct cmd __section ## _ ## _name = {                          \
                .name = (#_name),                                       \
                .args = (_args),                                        \
                .cmd = (_nlcmd),                                        \
@@ -141,14 +140,17 @@ struct chandef {
                .idby = (_idby),                                        \
                .handler = (_handler),                                  \
                .help = (_help),                                        \
-        }
+        };                                                             \
+       static struct cmd *__section ## _ ## _name ## _p                \
+       __attribute__((used,section("__cmd"))) = &__section ## _ ## _name
+
 #define SECTION(_name)                                                 \
-       extern struct cmd __section ## _ ## _name; /* sparse */         \
-       struct cmd __section ## _ ## _name                              \
-       __attribute__((used)) __attribute__((section("__cmd"))) = {     \
+       struct cmd __section ## _ ## _name = {                          \
                .name = (#_name),                                       \
                .hidden = 1,                                            \
-       }
+       };                                                              \
+       static struct cmd *__section ## _ ## _name ## _p                \
+       __attribute__((used,section("__cmd"))) = &__section ## _ ## _name
 
 #define DECLARE_SECTION(_name)                                         \
        extern struct cmd __section ## _ ## _name;