mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-23 18:14:13 +08:00
gas/ELF: allow "inheriting" section attributes and type
While --sectname-subst is nice, it isn't enough to e.g. mimic -f{function,data}-sections in assembly code, when such use is to be optional (e.g. dependent upon some configuration setting). Assign meaning to '+' and '-' as section attribute letters, allowing to inherit the prior section's attributes (and possibly type) along with adding or removing some. Note that documenting the interaction with '?' as undefined is a precautionary measure. While touching the function invocation, stop using |= on the result of obj_elf_parse_section_letters(): "attr" is firmly zero ahead of the call.
This commit is contained in:
parent
7b793987b5
commit
cefaa117f7
@ -822,10 +822,12 @@ obj_elf_change_section (const char *name,
|
||||
|
||||
static bfd_vma
|
||||
obj_elf_parse_section_letters (char *str, size_t len,
|
||||
bool *is_clone, bfd_vma *gnu_attr)
|
||||
bool *is_clone, int *inherit, bfd_vma *gnu_attr)
|
||||
{
|
||||
bfd_vma attr = 0;
|
||||
|
||||
*is_clone = false;
|
||||
*inherit = 0;
|
||||
|
||||
while (len > 0)
|
||||
{
|
||||
@ -923,6 +925,8 @@ obj_elf_parse_section_letters (char *str, size_t len,
|
||||
len -= (end - str);
|
||||
str = end;
|
||||
}
|
||||
else if (!attr && !*gnu_attr && (*str == '+' || *str == '-'))
|
||||
*inherit = *str == '+' ? 1 : -1;
|
||||
else
|
||||
as_fatal ("%s", bad_msg);
|
||||
}
|
||||
@ -1171,6 +1175,7 @@ obj_elf_section (int push)
|
||||
if (*input_line_pointer == '"')
|
||||
{
|
||||
bool is_clone;
|
||||
int inherit;
|
||||
|
||||
beg = demand_copy_C_string (&dummy);
|
||||
if (beg == NULL)
|
||||
@ -1178,8 +1183,15 @@ obj_elf_section (int push)
|
||||
ignore_rest_of_line ();
|
||||
return;
|
||||
}
|
||||
attr |= obj_elf_parse_section_letters (beg, strlen (beg),
|
||||
&is_clone, &gnu_attr);
|
||||
attr = obj_elf_parse_section_letters (beg, strlen (beg), &is_clone,
|
||||
&inherit, &gnu_attr);
|
||||
|
||||
if (inherit > 0)
|
||||
attr |= elf_section_flags (now_seg);
|
||||
else if (inherit < 0)
|
||||
attr = elf_section_flags (now_seg) & ~attr;
|
||||
if (inherit)
|
||||
type = elf_section_type (now_seg);
|
||||
|
||||
SKIP_WHITESPACE ();
|
||||
if (*input_line_pointer == ',')
|
||||
@ -1224,6 +1236,9 @@ obj_elf_section (int push)
|
||||
{
|
||||
++input_line_pointer;
|
||||
SKIP_WHITESPACE ();
|
||||
if (inherit && *input_line_pointer == ','
|
||||
&& (bfd_section_flags (now_seg) & SEC_MERGE) != 0)
|
||||
goto fetch_entsize;
|
||||
entsize = get_absolute_expression ();
|
||||
SKIP_WHITESPACE ();
|
||||
if (entsize < 0)
|
||||
@ -1233,6 +1248,12 @@ obj_elf_section (int push)
|
||||
entsize = 0;
|
||||
}
|
||||
}
|
||||
else if ((attr & SHF_MERGE) != 0 && inherit
|
||||
&& (bfd_section_flags (now_seg) & SEC_MERGE) != 0)
|
||||
{
|
||||
fetch_entsize:
|
||||
entsize = now_seg->entsize;
|
||||
}
|
||||
else if ((attr & SHF_MERGE) != 0)
|
||||
{
|
||||
as_warn (_("entity size for SHF_MERGE not specified"));
|
||||
@ -1248,6 +1269,9 @@ obj_elf_section (int push)
|
||||
{
|
||||
linked_to_section_index = strtoul (input_line_pointer, & input_line_pointer, 0);
|
||||
}
|
||||
else if (inherit && *input_line_pointer == ','
|
||||
&& (elf_section_flags (now_seg) & SHF_LINK_ORDER) != 0)
|
||||
goto fetch_linked_to;
|
||||
else
|
||||
{
|
||||
char c;
|
||||
@ -1260,6 +1284,17 @@ obj_elf_section (int push)
|
||||
match.linked_to_symbol_name = xmemdup0 (beg, length);
|
||||
}
|
||||
}
|
||||
else if ((attr & SHF_LINK_ORDER) != 0 && inherit
|
||||
&& (elf_section_flags (now_seg) & SHF_LINK_ORDER) != 0)
|
||||
{
|
||||
fetch_linked_to:
|
||||
if (now_seg->map_head.linked_to_symbol_name)
|
||||
match.linked_to_symbol_name =
|
||||
now_seg->map_head.linked_to_symbol_name;
|
||||
else
|
||||
linked_to_section_index =
|
||||
elf_section_data (now_seg)->this_hdr.sh_link;
|
||||
}
|
||||
|
||||
if ((attr & SHF_GROUP) != 0 && is_clone)
|
||||
{
|
||||
@ -1270,6 +1305,10 @@ obj_elf_section (int push)
|
||||
if ((attr & SHF_GROUP) != 0 && *input_line_pointer == ',')
|
||||
{
|
||||
++input_line_pointer;
|
||||
SKIP_WHITESPACE ();
|
||||
if (inherit && *input_line_pointer == ','
|
||||
&& (elf_section_flags (now_seg) & SHF_GROUP) != 0)
|
||||
goto fetch_group;
|
||||
match.group_name = obj_elf_section_name ();
|
||||
if (match.group_name == NULL)
|
||||
attr &= ~SHF_GROUP;
|
||||
@ -1286,6 +1325,14 @@ obj_elf_section (int push)
|
||||
else if (startswith (name, ".gnu.linkonce"))
|
||||
linkonce = 1;
|
||||
}
|
||||
else if ((attr & SHF_GROUP) != 0 && inherit
|
||||
&& (elf_section_flags (now_seg) & SHF_GROUP) != 0)
|
||||
{
|
||||
fetch_group:
|
||||
match.group_name = elf_group_name (now_seg);
|
||||
linkonce =
|
||||
(bfd_section_flags (now_seg) & SEC_LINK_ONCE) != 0;
|
||||
}
|
||||
else if ((attr & SHF_GROUP) != 0)
|
||||
{
|
||||
as_warn (_("group name for SHF_GROUP not specified"));
|
||||
|
@ -6818,6 +6818,12 @@ section is a member of a section group
|
||||
section is used for thread-local-storage
|
||||
@item ?
|
||||
section is a member of the previously-current section's group, if any
|
||||
@item +
|
||||
section inherits attributes and (unless explicitly specified) type from the
|
||||
previously-current section, adding other attributes as specified
|
||||
@item -
|
||||
section inherits attributes and (unless explicitly specified) type from the
|
||||
previously-current section, removing other attributes as specified
|
||||
@item R
|
||||
retained section (apply SHF_GNU_RETAIN to prevent linker garbage
|
||||
collection, GNU ELF extension)
|
||||
@ -6839,6 +6845,12 @@ section may have the executable (@code{x}) flag added. Also note that the
|
||||
@code{.attach_to_group} directive can be used to add a section to a group even
|
||||
if the section was not originally declared to be part of that group.
|
||||
|
||||
Note further that @code{+} and @code{-} need to come first and can only take
|
||||
the effect described here unless overridden by a target. The attributes
|
||||
inherited are those in effect at the time the directive is processed.
|
||||
Attributes added later (see above) will not be inherited. Using either
|
||||
together with @code{?} is undefined at this point.
|
||||
|
||||
The optional @var{type} argument may contain one of the following constants:
|
||||
|
||||
@table @code
|
||||
|
@ -280,6 +280,11 @@ if { [is_elf_format] } then {
|
||||
run_dump_test "section27"
|
||||
run_dump_test "section28"
|
||||
run_dump_test "section29"
|
||||
if { ![istarget "rx-*-*"] } then {
|
||||
run_dump_test "section30"
|
||||
} else {
|
||||
run_dump_test "section30" {{as -muse-conventional-section-names}}
|
||||
}
|
||||
run_dump_test "sh-link-zero"
|
||||
run_dump_test "size"
|
||||
run_dump_test "dwarf2-1" $dump_opts
|
||||
|
28
gas/testsuite/gas/elf/section30.d
Normal file
28
gas/testsuite/gas/elf/section30.d
Normal file
@ -0,0 +1,28 @@
|
||||
#as: --sectname-subst
|
||||
#readelf: -SW
|
||||
#name: --sectname-subst plus section attr/type inherting
|
||||
# Targets setting NO_PSEUDO_DOT don't allow macros of certain names.
|
||||
#notarget: m681*-*-* m68hc1*-*-* s12z-*-* spu-*-* xgate-*-* z80-*-*
|
||||
|
||||
#...
|
||||
\[..\] \.group +GROUP +[0-9a-f]+ [0-9a-f]+ 0+c 04 +[1-9][0-9]* +[1-9][0-9]* +4
|
||||
\[..\] \.text +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 AX 0 0 +[1-9][0-9]*
|
||||
\[..\] \.data +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 WA 0 0 +[1-9][0-9]*
|
||||
\[..\] \.bss +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 WA 0 0 +[1-9][0-9]*
|
||||
#...
|
||||
\[..\] \.text\.func1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
|
||||
\[..\] \.text\.func2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ [0-9a-f]+ 00 AX 0 0 +[1-9][0-9]*
|
||||
\[..\] \.data\.data1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+1 00 WA 0 0 1
|
||||
#...
|
||||
\[..\] \.bss\.data2 +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+2 00 WA 0 0 1
|
||||
\[..\] \.rodata +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 A 0 0 1
|
||||
\[..\] \.rodata\.data3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+3 00 A 0 0 1
|
||||
\[..\] \.rodata\.str1\.1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 01 AMS 0 0 1
|
||||
\[..\] \.rodata\.str1\.1\.str1 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+8 01 AMS 0 0 1
|
||||
\[..\] \.rodata\.2 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 AL [1-9] 0 1
|
||||
\[..\] \.rodata\.2\.data4 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+4 00 AL [1-9] 0 1
|
||||
\[..\] \.bss\.data5 +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+5 00 WA 0 0 1
|
||||
\[..\] \.rodata\.3 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+0 00 AG 0 0 1
|
||||
\[..\] \.rodata\.3\.data6 +PROGBITS +[0-9a-f]+ [0-9a-f]+ 0+6 00 AG 0 0 1
|
||||
\[..\] \.bss\.data7 +NOBITS +[0-9a-f]+ [0-9a-f]+ 0+7 00 WA 0 0 1
|
||||
#pass
|
67
gas/testsuite/gas/elf/section30.s
Normal file
67
gas/testsuite/gas/elf/section30.s
Normal file
@ -0,0 +1,67 @@
|
||||
.macro func name:req
|
||||
.pushsection %S.\name, "+"
|
||||
.type \name, %function
|
||||
.global \name
|
||||
.hidden \name
|
||||
\name:
|
||||
.endm
|
||||
|
||||
.macro data name:req
|
||||
.pushsection %S.\name, "+"
|
||||
.type \name, %object
|
||||
\name:
|
||||
.endm
|
||||
|
||||
.macro end name:req
|
||||
.size \name, . - \name
|
||||
.popsection
|
||||
.endm
|
||||
|
||||
|
||||
.text
|
||||
func func1
|
||||
.nop
|
||||
end func1
|
||||
|
||||
func func2
|
||||
.nop
|
||||
.nop
|
||||
end func2
|
||||
|
||||
.data
|
||||
data data1
|
||||
.byte 1
|
||||
end data1
|
||||
|
||||
.section .bss
|
||||
data data2
|
||||
.skip 2
|
||||
end data2
|
||||
|
||||
.section .rodata, "a", %progbits
|
||||
data data3
|
||||
.byte 3, 3, 3
|
||||
end data3
|
||||
|
||||
.section .rodata.str1.1, "aMS", %progbits, 1
|
||||
data str1
|
||||
.asciz "string1"
|
||||
end str1
|
||||
|
||||
.section .rodata.2, "ao", %progbits, func1
|
||||
data data4
|
||||
.byte 4, 4, 4, 4
|
||||
end data4
|
||||
.pushsection .bss.data5, "-o", %nobits
|
||||
.type data5, %object
|
||||
data5: .fill 5
|
||||
end data5
|
||||
|
||||
.section .rodata.3, "aG", %progbits, sig1, comdat
|
||||
data data6
|
||||
.byte 6, 6, 6, 6, 6, 6
|
||||
end data6
|
||||
.pushsection .bss.data7, "-G", %nobits
|
||||
.type data7, %object
|
||||
data7: .skip 7
|
||||
end data7
|
Loading…
Reference in New Issue
Block a user