On Mon, Jun 13, 2011 at 10:03 PM, Nicolas Pitre
<nicolas.pi...@linaro.org> wrote:
> Hello Michael,
>
> We do have more and more instances of the following issues turning up in
> the kernel requiring toolchain assistance to solve the problem properly.
> Could you or someone from your team follow this up please?

Just a bit of extra context here:

The problem my patch intends to solve is just one instance of a
general class of problems: in general, it's not possible to query,
save or restore aspects of the assembler state during assembly.

gas supports a few special-purposes state management features such as
.pushsection/.popsection, but for most aspects of the assembler state
there are no such facilities.

Things we'd like to achieve are:

    Creating sections with names based on that of the current section
    Temporarily overriding .arch (for example, to build in
CPU-specific optimisations in a file built for a more generic
architecture).

Hacks like the one I suggest could provide a way to solve problems
such as these.  However, I don't know much about gas internals, so
there may be a much cleaner way of achieving these things than the
method I propose.

Cheers
---Dave

>
> ---------- Forwarded message ----------
> Date: Tue, 1 Feb 2011 12:16:48 +0000
> From: Dave Martin <dave.mar...@linaro.org>
> To: binut...@sourceware.org
> Cc: linaro-toolchain <linaro-toolchain@lists.linaro.org>
> Subject: Generating ancilliary sections with gas
>
> Hi all,
>
> Every now and again I come across a situation where it would be
> really useful to be able to query the assembler state during
> assembly: for example, to query and do something based on the
> current section name.  This makes it possible to write generic
> macros to do certain things which otherwise require manual
> maintenance, or complex and fragile external preprocessing.
>
> Below, I give a real-world example of the problem, and sketch out
> a possible solution.
>
> What do people think of this approach?  Does anyone have any better
> ideas on how to solve this?
>
> Cheers
> ---Dave
>
> EXAMPLE
>
> An example is the generation of custom ancilliary sections.
> Suppose you want to write macros which record fixup information.
> Currently, there's no way to put each fixup in an appropriately
> named section automatically within gas.  Tellingly, gas has had
> to grow the ability to do this internally at least for ARM,
> since the exception handling information in .ARM.ex{idx,tab}*
> must go in sections with names based on the associated section
> name.  However, this ancillary section generation support is
> neither flexible nor exposed to the user.
>
> By putting fixups in sections whose names are based on the name
> of the section they refer to, selective link-time discard of the
> fixups (and hence the code referenced by the fixups) will work;
> otherwise it doesn't.  This would help avoid a situation where we
> have to keep dead code in the kernel because custom fixups are
> applied to it: at run-time, the code gets fixed up, then is
> thrown away.  The fixups can't be selectively discarded because
> they are all in the same section: we seem have to no good
> way to separate them out into separate sections appropriately.
>
> For context, see:
> http://www.spinics.net/lists/arm-kernel/msg112268.html
>
> PROPOSAL
>
> To solve the problem of generating custom ancillary sections
> during assembly, here's a simple proposal: introducing a new kind of
> macro argument can make aspects of the assembler state available to
> macros in a flexible way, with only minimal implementation
> required.
>
> Basically, the macro qualifier field could be used to identify
> arguments which are filled in by the assembler with information
> about the assembly state, rather than being filled in by the
> invoker of the macro: e.g.:
>
> .macro mymacro name:req, flags, secname:current_section
>        /* ... */
>        .pushsection "\secname\name", "\flags"
>        /* ... */
>        .popsection
> .endm
>
> /* ... */
>
> mymacro .ancillary, "a"
>
> During expansion, \name and \flags are expanded as normal.
> But \secname is substituted instead with the current section name,
> so the macro expansion would look like this:
>
> /* ... */
> .pushsection ".text.ancillary", "a"
> /* ... */
> .popsection
>
> Without the special :current_section argument, it doesn't appear
> possible to implement a macro such as mymacro in a generic way.
>
> This surely isn't the only way to achieve the goal, and it's
> probably not the best way, but it does have some desirable
> features.
>
> Principally, while a new pseudo-op(s) could have been defined to
> append text to the current section name, etc., allowing the current
> section name to be appear as a macro parameter avoids prejudicing
> the way the text is used.  So there should never be a need to
> introduce additional pseudo-ops to do things with the current
> section name: with this patch, the user can always implement their
> own macro to do the desired thing.  This gets the desired
> behaviour and maximum flexibility, while keeping the implementation
> in gas very simple.
>
> Also, using the macro expansion system in this way allows the
> caller a free choice of macro parameter names, and so pretty much
> guarantees that existing code won't get broken by the change.
>
>
> Because my hack is currently simplistic, it has shortcomings: in
> particular, it's not desirable to parse an argument from the
> invocation line at all to fill a :current_section argument.
> Currently, an argument is read in if present, but its value is
> ignored and the current section name pasted in at macro expansion
> time instead.  However, that should be straightforward to fix with
> a bit more code.
>
>
> Of course, there's no reason only to expose the current section name
> in this way.  Any aspect of the the assembler state (current
> subsection, current section flags, current instruction set, current
> macro mode,  etc.) could be made available in a similar way.
>
>
> USAGE EXAMPLE AND PATCH
>
> Note that the specific implementation described here is intended
> to be illustrative, rather than complete or final.
>
> binutils$ cat <<EOF >tst.s
> .macro push_ancillary_section name:req, flags, csec:current_section
>        .pushsection "\name\csec", "\flags"
> .endm
>
> .macro register_fixup
>        _register_fixup 100\@
> .endm
>
> .macro _register_fixup label:req
> \label :
>        push_ancillary_section .fixup, "a"
>        .long \label\(b)
>        .popsection
> .endm
>
>        .long   1
>        register_fixup
>        .long   2
>
> .data
>        .long   3
>        register_fixup
>        .long   4
>        .long   5
>        register_fixup
>        .long   6
> EOF
>
> binutils$ gas/as-new -ahlms -o tst.o tst.s
> ARM GAS  tst.s                  page 1
>
>
>   1                    .macro push_ancillary_section name:req, flags, 
> csec:current_section
>   2                            .pushsection "\name\csec", "\flags"
>   3                    .endm
>   4
>   5                    .macro register_fixup
>   6                            _register_fixup 100\@
>   7                    .endm
>   8
>   9                    .macro _register_fixup label:req
>  10                    \label :
>  11                            push_ancillary_section .fixup, "a"
>  12                            .long \label\(b)
>  13                            .popsection
>  14                    .endm
>  15
>  16 0000 01000000              .long   1
>  17                            register_fixup
>  17                    >  _register_fixup 1000
>  17                    >> 1000:
>  17                    >>  push_ancillary_section .fixup,"a"
>  17                    >>>  .pushsection ".fixup.text","a"
>  17 0000 04000000      >>  .long 1000b
>  17                    >>  .popsection
>  18 0004 02000000              .long   2
>  19
>  20                    .data
>  21 0000 03000000              .long   3
>  22                            register_fixup
>  22                    >  _register_fixup 1003
>  22                    >> 1003:
>  22                    >>  push_ancillary_section .fixup,"a"
>  22                    >>>  .pushsection ".fixup.data","a"
>  22 0000 04000000      >>  .long 1003b
>  22                    >>  .popsection
>  23 0004 04000000              .long   4
>  24 0008 05000000              .long   5
>  25                            register_fixup
>  25                    >  _register_fixup 1006
>  25                    >> 1006:
>  25                    >>  push_ancillary_section .fixup,"a"
>  25                    >>>  .pushsection ".fixup.data","a"
>  25 0004 0C000000      >>  .long 1006b
>  25                    >>  .popsection
>  26 000c 06000000              .long   6
> ARM GAS  tst.s                  page 2
>
>
> NO DEFINED SYMBOLS
>
> NO UNDEFINED SYMBOLS
>
> binutils$ arm-linux-gnueabi-objdump -rs tst.o
>
> tst.o:     file format elf32-littlearm
>
> RELOCATION RECORDS FOR [.fixup.text]:
> OFFSET   TYPE              VALUE
> 00000000 R_ARM_ABS32       .text
>
>
> RELOCATION RECORDS FOR [.fixup.data]:
> OFFSET   TYPE              VALUE
> 00000000 R_ARM_ABS32       .data
> 00000004 R_ARM_ABS32       .data
>
>
> Contents of section .text:
>  0000 01000000 02000000                    ........
> Contents of section .data:
>  0000 03000000 04000000 05000000 06000000  ................
> Contents of section .fixup.text:
>  0000 04000000                             ....
> Contents of section .fixup.data:
>  0000 04000000 0c000000                    ........
> Contents of section .ARM.attributes:
>  0000 41150000 00616561 62690001 0b000000  A....aeabi......
>  0010 08010901 2c01                        ....,.
>
> diff --git a/gas/macro.c b/gas/macro.c
> index e392883..95c4de1 100644
> --- a/gas/macro.c
> +++ b/gas/macro.c
> @@ -516,6 +516,8 @@ do_formals (macro_entry *macro, int idx, sb *in)
>            formal->type = FORMAL_REQUIRED;
>          else if (strcmp (qual.ptr, "vararg") == 0)
>            formal->type = FORMAL_VARARG;
> +         else if (strcmp (qual.ptr, "current_section") == 0)
> +           formal->type = FORMAL_CURRENT_SECTION;
>          else
>            as_bad_where (macro->file,
>                          macro->line,
> @@ -540,6 +542,15 @@ do_formals (macro_entry *macro, int idx, sb *in)
>                            name,
>                            macro->name);
>            }
> +         else if (formal->type == FORMAL_CURRENT_SECTION)
> +           {
> +             sb_reset (&formal->def);
> +             as_warn_where (macro->file,
> +                           macro->line,
> +                           _("Pointless default value for current_section 
> parameter `%s' in macro `%s'"),
> +                           name,
> +                           macro->name);
> +           }
>        }
>
>       /* Add to macro's hash table.  */
> @@ -734,7 +745,11 @@ sub_actual (int start, sb *in, sb *t, struct 
> hash_control *formal_hash,
>     ptr = (formal_entry *) hash_find (formal_hash, sb_terminate (t));
>   if (ptr)
>     {
> -      if (ptr->actual.len)
> +      if (ptr->type == FORMAL_CURRENT_SECTION)
> +       {
> +         sb_add_string (out, segment_name (now_seg));
> +       }
> +      else if (ptr->actual.len)
>        {
>          sb_add_sb (out, &ptr->actual);
>        }
> diff --git a/gas/macro.h b/gas/macro.h
> index edc1b6b..ea6cabb 100644
> --- a/gas/macro.h
> +++ b/gas/macro.h
> @@ -38,7 +38,8 @@ enum formal_type
>   {
>     FORMAL_OPTIONAL,
>     FORMAL_REQUIRED,
> -    FORMAL_VARARG
> +    FORMAL_VARARG,
> +    FORMAL_CURRENT_SECTION,
>   };
>
>  /* Describe the formal arguments to a macro.  */
>
>
> _______________________________________________
> linaro-toolchain mailing list
> linaro-toolchain@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-toolchain
>
> _______________________________________________
> linaro-toolchain mailing list
> linaro-toolchain@lists.linaro.org
> http://lists.linaro.org/mailman/listinfo/linaro-toolchain
>

_______________________________________________
linaro-toolchain mailing list
linaro-toolchain@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-toolchain

Reply via email to