Translate asm version of ELFNOTE macro into preprocessor macro
PATCH 1/1 Translate asm version of ELFNOTE macro into preprocessor macro
Hi,
I've come across some problems with the assembly version of the ELFNOTE macro currently in -mm. (in x86-put-note-sections-into-a-pt_note-segment-in-vmlinux.patch)
The first is that older gas does not support :varargs in .macro definitions (in my testing 2.17 does while 2.15 does not, I don't know when it became supported). The Changes file says binutils >= 2.12 so I think we need to avoid using it. There are no other uses in mainline or -mm. Old gas appears to just ignore it so you get "too many arguments" type errors.
Secondly it seems that passing strings as arguments to assembler macros is broken without varargs. It looks like they get unquoted or each character is treated as a separate argument or something and this causes all manner of grief. I think this is because of the use of -traditional when compiling assembly files.
Therefore I have translated the assembler macro into a pre-processor macro.
I added the desctype as a separate argument instead of including it with the descdata as the previous version did since -traditional means the ELFNOTE definition after the #else needs to have the same number of arguments (I think so anyway, the -traditional CPP semantics are pretty fscking strange!).
With this patch I am able to define elfnotes in assembly like this with both old and new assemblers.
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz, "linux") ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz, "2.6") ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz, "xen-3.0") ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, .long, __PAGE_OFFSET)
Which seems reasonable enough.
include/linux/elfnote.h +17 -15
@@ -31,22 +31,24 @@/* * Generate a structure with the same shape as Elf{32,64}_Nhdr (which * turn out to be the same size and shape), followed by the name and -* desc data with appropriate padding. The 'desc' argument includes -* the assembler pseudo op defining the type of the data: .asciz -* "hello, world" +* desc data with appropriate padding. The 'desctype' argument is the +* assembler pseudo op defining the type of the data e.g. .asciz while +* 'descdata' is the data itself e.g. "hello, world". +* +* e.g. ELFNOTE(XYZCo, 42, .asciz, "forty-two") +* ELFNOTE(XYZCo, 12, .long, 0xdeadbeef) */ -.macro ELFNOTE name type desc:vararg -.pushsection ".note.\name" - .align 4 - .long 2f - 1f /* namesz */ - .long 4f - 3f /* descsz */ - .long \type -1:.asciz "\name" -2:.align 4 -3:\desc -4:.align 4 -.popsection -.endm +#define ELFNOTE(name, type, desctype, descdata) \ +.pushsection .note.name ; \ + .align 4 ; \ + .long 2f - 1f /* namesz */ ; \ + .long 4f - 3f /* descsz */ ; \ + .long type ; \ +1:.asciz "name" ; \ +2:.align 4 ; \ +3:desctype descdata ; \ +4:.align 4 ; \ +.popsection ;#else /* !__ASSEMBLER__ */ #include <linux/elf.h> /*
Quoted 7 lines · Ian Campbell
The first is that older gas does not support :varargs in .macro definitions (in my testing 2.17 does while 2.15 does not, I don't know when it became supported). The Changes file says binutils >= 2.12 so I think we need to avoid using it. There are no other uses in mainline or -mm. Old gas appears to just ignore it so you get "too many arguments" type errors.
OK, seems reasonable. Eric Biederman solved this by having NOTE/ENDNOTE (or something like that) in his "bzImage with ELF header" patch, but I don't remember it being used in any way which is incompatible with using a CPP macro.
J
Quoted 8 lines · Jeremy Fitzhardinge
Quoted 7 lines · Ian Campbell
The first is that older gas does not support :varargs in .macro definitions (in my testing 2.17 does while 2.15 does not, I don't know when it became supported). The Changes file says binutils >= 2.12 so I think we need to avoid using it. There are no other uses in mainline or -mm. Old gas appears to just ignore it so you get "too many arguments" type errors.
Quoted 4 lines
OK, seems reasonable. Eric Biederman solved this by having NOTE/ENDNOTE (or something like that) in his "bzImage with ELF header" patch, but I don't remember it being used in any way which is incompatible with using a CPP macro.
I can't find that patch, does NOTE/ENDNOTE just do the push/pop .note section?
That would solve the problem with the first argument of the macro being a string but the final argument could still be for .asciz note contents.
Ian.
Quoted 9 lines · Ian Campbell
Quoted 2 lines
OK, seems reasonable. Eric Biederman solved this by having NOTE/ENDNOTE (or something like that) in his "bzImage with ELF header" patch, but I don't remember it being used in any way which is incompatible with using a CPP macro.
I can't find that patch, does NOTE/ENDNOTE just do the push/pop .note section?
That would solve the problem with the first argument of the macro being a string but the final argument could still be for .asciz note contents.
It looks like:
.macro note name, type
.balign 4
.int 2f - 1f # n_namesz
.int 4f - 3f # n_descsz
.int \type # n_type
.balign 4
1: .asciz "\name"
2: .balign 4
3:
.endm
.macro enote
4: .balign 4
.endm
so it allows you to put arbitrary stuff in the desc part of the note. The downside is that its a little more cumbersome syntactically for the common case.
J
Quoted 31 lines · Jeremy Fitzhardinge
Quoted 6 lines · Ian Campbell
Quoted 5 lines
OK, seems reasonable. Eric Biederman solved this by having NOTE/ENDNOTE (or something like that) in his "bzImage with ELF header" patch, but I don't remember it being used in any way which is incompatible with using a CPP macro.
Quoted 6 lines
I can't find that patch, does NOTE/ENDNOTE just do the push/pop .note section?
That would solve the problem with the first argument of the macro being a string but the final argument could still be for .asciz note contents.
It looks like:
.macro note name, type
.balign 4
.int 2f - 1f #n_namesz
.int 4f - 3f #n_descsz
.int \type #n_type
.balign 4
1: .asciz "\name"
2: .balign 4
3:
.endm
.macro enote
4: .balign 4
.endm
Quoted 2 lines
so it allows you to put arbitrary stuff in the desc part of the note. The downside is that its a little more cumbersome syntactically for the common case.
I don't expect it to be much more cumbersome, as two pieces, and you need the extra alignment at the end to ensure each not entry is 4 byte aligned. Being able to push and pop a section wouldn't hurt either.
Eric
Quoted 11 lines · Eric W. Biederman
Quoted 8 lines · Jeremy Fitzhardinge
Quoted 6 lines · Ian Campbell
Quoted 6 lines
OK, seems reasonable. Eric Biederman solved this by having NOTE/ENDNOTE (or something like that) in his "bzImage with ELF header" patch, but I don't remember it being used in any way which is incompatible with using a CPP macro.
Quoted 7 lines
Quoted 7 lines
Quoted 7 lines
I can't find that patch, does NOTE/ENDNOTE just do the push/pop .note section?
That would solve the problem with the first argument of the macro being a string but the final argument could still be for .asciz note contents.
I remember now why I decided to use the assembler macro rather than cpp. The macro names the section after the note name (".note.NAME"), and it needs to be quoted so that the name can have spaces and other characters which would otherwise upset the assembler. I couldn't work out a clean way to do this with the C preprocessor, since "as" doesn't support string concatenation like C does.
Quoted 2 lines
I don't expect it to be much more cumbersome, as two pieces, and you need the extra alignment at the end to ensure each not entry is 4 byte aligned.
Isn't it enough that each entry start have the alignment? But you need some kind of end marker to get the size of the desc field regardless.
Quoted 2 lines
Being able to
push and pop a section wouldn't hurt either.
Yes, I think having each note contain its own .pushsection/popsection is the cleaner way of doing it.
J
Quoted 7 lines · Jeremy Fitzhardinge
I remember now why I decided to use the assembler macro rather than cpp. The macro names the section after the note name (".note.NAME"), and it needs to be quoted so that the name can have spaces and other characters which would otherwise upset the assembler. I couldn't work out a clean way to do this with the C preprocessor, since "as" doesn't support string concatenation like C does.
Surprisingly string concatenation doesn't appear to be required for the majority of punctuation, at least so far as I can tell with this test patch (this is a xen-unstable kernel I had lying around so don't pay too much attention to head-xen.S bit). The only problem I found is comma, which can't be escaped.
I've no idea how reliably this works across tool chain versions etc though. It worked for me ;-)
include/linux/elfnote.h +1 -1
@@ -39,7 +39,7 @@* ELFNOTE(XYZCo, 12, .long, 0xdeadbeef) */ #define ELFNOTE(name, type, desctype, descdata) \ -.pushsection .note.name ; \ +.pushsection ".note.name" ; \ .align 4 ; \ .long 2f - 1f /* namesz */ ; \ .long 4f - 3f /* descsz */ ; \
linux-2.6-xen-sparse/arch/i386/kernel/head-xen.S +8 -0
@@ -199,3 +199,11 @@ ENTRY(cpu_gdt_table) ELFNOTE(Xen, XEN_ELFNOTE_PAE_MODE, .asciz, "no") #endif ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz, "generic") + + ELFNOTE(XYZ Co., 42, .asciz, "forty-two") + ELFNOTE(XYZ Co., 12, .long, 0xdeadbeef) + ELFNOTE(!\"£$%^\\&, 12, .long, 0xdeadbeef) + ELFNOTE(*\(\)-+-=<, 12, .long, 0xdeadbeef) + ELFNOTE(>./?\;\'#:, 12, .long, 0xdeadbeef) + ELFNOTE(@~, 12, .long, 0xdeadbeef) +
$ readelf -S --segments arch/i386/kernel/head-xen.o ... [ 7] .note.Xen NOTE 00000000 002260 000144 00 0 0 4 [ 8] .rel.note.Xen REL 00000000 003018 000010 08 15 7 4 [ 9] .note.XYZ Co. NOTE 00000000 0023a4 000038 00 0 0 4 [10] .note.!"£$%^\& NOTE 00000000 0023dc 00001c 00 0 0 4 [11] .note.*()-+-=< NOTE 00000000 0023f8 00001c 00 0 0 4 [12] .note.>./?;'#: NOTE 00000000 002414 00001c 00 0 0 4 [13] .note.@~ NOTE 00000000 002430 000014 00 0 0 4 ...
$ objdump -j .notes -s vmlinux ... 85a8 72696300 08000000 0a000000 2a000000 ric.........*... 85b8 58595a20 436f2e00 666f7274 792d7477 XYZ Co..forty-tw 85c8 6f000000 08000000 04000000 0c000000 o............... 85d8 58595a20 436f2e00 efbeadde 0a000000 XYZ Co.......... 85e8 04000000 0c000000 2122c2a3 24255e5c ........!"..$%^\ 85f8 26000000 efbeadde 09000000 04000000 &............... 8608 0c000000 2a28292d 2b2d3d3c 00000000 ....*()-+-=<.... 8618 efbeadde 09000000 04000000 0c000000 ................ 8628 3e2e2f3f 3b27233a 00000000 efbeadde >./?;'#:........ 8638 03000000 04000000 0c000000 407e0000 ............@~.. 8648 efbeadde .... ...
Quoted 9 lines · Ian Campbell
Surprisingly string concatenation doesn't appear to be required for the majority of punctuation, at least so far as I can tell with this test patch (this is a xen-unstable kernel I had lying around so don't pay too much attention to
head-xen.Sbit). The only problem I found is comma, which can't be escaped.I've no idea how reliably this works across tool chain versions etc though. It worked for me ;-)
I guess that's a broad enough selection of names. I had assumed it would impose normal symbol-like restrictions on the unquoted section name. (I guess ';' would also need quoting.)
J