Browse Source

ld: Support customized output section type

bfd/
    PR ld/28841
    * bfd-in2.h (struct bfd_section): Add type.
    (discarded_section): Add field.
    * elf.c (elf_fake_sections): Handle bfd_section::type.
    * section.c (BFD_FAKE_SECTION): Add field.
    * mri.c (mri_draw_tree): Update function call.

ld/
    PR ld/28841
    * ld.texi: Document new output section type.
    * ldlex.l: Add new token TYPE.
    * ldgram.y: Handle TYPE=exp.
    * ldlang.h: Add type_section to list of section types.
    * ldlang.c (lang_add_section): Handle type_section.
    (map_input_to_output_sections): Handle type_section.
    * testsuite/ld-scripts/output-section-types.t: Add tests.
    * testsuite/ld-scripts/output-section-types.d: Update.
gdb-12-branch
Fangrui Song 4 years ago
committed by Nick Clifton
parent
commit
c212f39d9a
  1. 10
      bfd/ChangeLog
  2. 7
      bfd/bfd-in2.h
  3. 4
      bfd/elf.c
  4. 4
      bfd/section.c
  5. 13
      ld/ChangeLog
  6. 3
      ld/NEWS
  7. 16
      ld/ld.texi
  8. 11
      ld/ldgram.y
  9. 55
      ld/ldlang.c
  10. 7
      ld/ldlang.h
  11. 1
      ld/ldlex.l
  12. 4
      ld/mri.c
  13. 18
      ld/testsuite/ld-scripts/output-section-types.d
  14. 7
      ld/testsuite/ld-scripts/output-section-types.t

10
bfd/ChangeLog

@ -1,3 +1,13 @@
2022-02-16 Fangrui Song <maskray@google.com>
Nick Clifton <nickc@redhat.com>
PR ld/28841
* bfd-in2.h (struct bfd_section): Add type.
(discarded_section): Add field.
* elf.c (elf_fake_sections): Handle bfd_section::type.
* section.c (BFD_FAKE_SECTION): Add field.
* mri.c (mri_draw_tree): Update function call.
2022-02-11 Michael Forney <mforney@mforney.org>
* bfd.c (bfd_set_gp_value): Remove return with expression

7
bfd/bfd-in2.h

@ -1170,6 +1170,9 @@ typedef struct bfd_section
This is used when support for non-contiguous memory regions is enabled. */
struct bfd_section *already_assigned;
/* Explicitly specified section type, if non-zero. */
unsigned int type;
} asection;
/* Relax table contains information about instructions which can
@ -1352,8 +1355,8 @@ discarded_section (const asection *sec)
/* symbol, symbol_ptr_ptr, */ \
(struct bfd_symbol *) SYM, &SEC.symbol, \
\
/* map_head, map_tail, already_assigned */ \
{ NULL }, { NULL }, NULL \
/* map_head, map_tail, already_assigned, type */ \
{ NULL }, { NULL }, NULL, 0 \
\
}

4
bfd/elf.c

@ -3280,7 +3280,9 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg)
/* If the section type is unspecified, we set it based on
asect->flags. */
if ((asect->flags & SEC_GROUP) != 0)
if (asect->type != 0)
sh_type = asect->type;
else if ((asect->flags & SEC_GROUP) != 0)
sh_type = SHT_GROUP;
else
sh_type = bfd_elf_get_default_section_type (asect->flags);

4
bfd/section.c

@ -737,8 +737,8 @@ CODE_FRAGMENT
. {* symbol, symbol_ptr_ptr, *} \
. (struct bfd_symbol *) SYM, &SEC.symbol, \
. \
. {* map_head, map_tail, already_assigned *} \
. { NULL }, { NULL }, NULL \
. {* map_head, map_tail, already_assigned, type *} \
. { NULL }, { NULL }, NULL, 0 \
. \
. }
.

13
ld/ChangeLog

@ -1,3 +1,16 @@
2022-02-16 Fangrui Song <maskray@google.com>
Nick Clifton <nickc@redhat.com>
PR ld/28841
* ld.texi: Document new output section type.
* ldlex.l: Add new token TYPE.
* ldgram.y: Handle TYPE=exp and READONLY (TYPE=exp).
* ldlang.h: Add type_section to list of section types.
* ldlang.c (lang_add_section): Handle type_section.
(map_input_to_output_sections): Handle type_section.
* testsuite/ld-scripts/output-section-types.t: Add tests.
* testsuite/ld-scripts/output-section-types.d: Update.
2022-02-02 Nick Clifton <nickc@redhat.com>
* po/fr.po: Updated French translation.

3
ld/NEWS

@ -1,5 +1,8 @@
-*- text -*-
* TYPE=<type> is now supported in an output section description to set the
section type value.
Changes in 2.38:
* Add -z pack-relative-relocs/-z no pack-relative-relocs to x86 ELF

16
ld/ld.texi

@ -5483,13 +5483,23 @@ loaded into memory when the program is run.
@item READONLY
The section should be marked as read-only.
@item DSECT
@itemx COPY
@itemx INFO
@itemx OVERLAY
@item COPY
@item INFO
@item OVERLAY
These type names are supported for backward compatibility, and are
rarely used. They all have the same effect: the section should be
marked as not allocatable, so that no memory is allocated for the
section when the program is run.
@item TYPE = @var{type}
Set the section type to the integer @var{type}. When generating an ELF
output file, type names @code{SHT_PROGBITS}, @code{SHT_STRTAB},
@code{SHT_NOTE}, @code {SHT_NOBITS}, @code{SHT_INIT_ARRAY},
@code{SHT_FINI_ARRAY}, and @code{SHT_PREINIT_ARRAY} are also allowed
for @var{type}. It is the user's responsibility to ensure that any
special requirements of the section type are met.
@item READONLY ( TYPE = @var{type} )
This form of the syntax combines the @var{READONLY} type with the
type specified by @var{type}.
@end table
@kindex NOLOAD

11
ld/ldgram.y

@ -47,6 +47,7 @@
#endif
static enum section_type sectype;
static etree_type *sectype_value;
static lang_memory_region_type *region;
static bool ldgram_had_keep = false;
@ -139,6 +140,7 @@ static int error_index;
%token LD_FEATURE
%token NOLOAD DSECT COPY INFO OVERLAY
%token READONLY
%token TYPE
%token DEFINED TARGET_K SEARCH_DIR MAP ENTRY
%token <integer> NEXT
%token SIZEOF ALIGNOF ADDR LOADADDR MAX_K MIN_K
@ -1058,9 +1060,8 @@ section: NAME
{
ldlex_popstate ();
ldlex_wild ();
lang_enter_output_section_statement($1, $3, sectype,
$5, $7, $4,
$8, $6);
lang_enter_output_section_statement ($1, $3, sectype,
sectype_value, $5, $7, $4, $8, $6);
}
'{'
statement_list_opt
@ -1130,8 +1131,10 @@ type:
| COPY { sectype = noalloc_section; }
| INFO { sectype = noalloc_section; }
| OVERLAY { sectype = noalloc_section; }
| READONLY '(' TYPE '=' exp ')' { sectype = typed_readonly_section; sectype_value = $5; }
| READONLY { sectype = readonly_section; }
;
| TYPE '=' exp { sectype = type_section; sectype_value = $3; }
;
atype:
'(' type ')'

55
ld/ldlang.c

@ -1891,8 +1891,8 @@ lang_insert_orphan (asection *s,
address = exp_intop (0);
os_tail = (lang_output_section_statement_type **) lang_os_list.tail;
os = lang_enter_output_section_statement (secname, address, normal_section,
NULL, NULL, NULL, constraint, 0);
os = lang_enter_output_section_statement (
secname, address, normal_section, 0, NULL, NULL, NULL, constraint, 0);
if (add_child == NULL)
add_child = &os->children;
@ -2635,10 +2635,12 @@ lang_add_section (lang_statement_list_type *ptr,
case normal_section:
case overlay_section:
case first_overlay_section:
case type_section:
break;
case noalloc_section:
flags &= ~SEC_ALLOC;
break;
case typed_readonly_section:
case readonly_section:
flags |= SEC_READONLY;
break;
@ -4209,6 +4211,7 @@ map_input_to_output_sections
{
lang_output_section_statement_type *tos;
flagword flags;
unsigned int type = 0;
switch (s->header.type)
{
@ -4264,6 +4267,42 @@ map_input_to_output_sections
case readonly_section:
flags |= SEC_READONLY;
break;
case typed_readonly_section:
flags |= SEC_READONLY;
/* Fall through. */
case type_section:
if (os->sectype_value->type.node_class == etree_name
&& os->sectype_value->type.node_code == NAME)
{
const char *name = os->sectype_value->name.name;
if (strcmp (name, "SHT_PROGBITS") == 0)
type = SHT_PROGBITS;
else if (strcmp (name, "SHT_STRTAB") == 0)
type = SHT_STRTAB;
else if (strcmp (name, "SHT_NOTE") == 0)
type = SHT_NOTE;
else if (strcmp (name, "SHT_NOBITS") == 0)
type = SHT_NOBITS;
else if (strcmp (name, "SHT_INIT_ARRAY") == 0)
type = SHT_INIT_ARRAY;
else if (strcmp (name, "SHT_FINI_ARRAY") == 0)
type = SHT_FINI_ARRAY;
else if (strcmp (name, "SHT_PREINIT_ARRAY") == 0)
type = SHT_PREINIT_ARRAY;
else
einfo (_ ("%F%P: invalid type for output section `%s'\n"),
os->name);
}
else
{
exp_fold_tree_no_dot (os->sectype_value);
if (expld.result.valid_p)
type = expld.result.value;
else
einfo (_ ("%F%P: invalid type for output section `%s'\n"),
os->name);
}
break;
case noload_section:
if (bfd_get_flavour (link_info.output_bfd)
== bfd_target_elf_flavour)
@ -4276,6 +4315,7 @@ map_input_to_output_sections
init_os (os, flags | SEC_READONLY);
else
os->bfd_section->flags |= flags;
os->bfd_section->type = type;
break;
case lang_input_section_enum:
break;
@ -7506,6 +7546,7 @@ lang_output_section_statement_type *
lang_enter_output_section_statement (const char *output_section_statement_name,
etree_type *address_exp,
enum section_type sectype,
etree_type *sectype_value,
etree_type *align,
etree_type *subalign,
etree_type *ebase,
@ -7523,10 +7564,12 @@ lang_enter_output_section_statement (const char *output_section_statement_name,
os->addr_tree = address_exp;
}
os->sectype = sectype;
if (sectype != noload_section)
os->flags = SEC_NO_FLAGS;
else
if (sectype == type_section || sectype == typed_readonly_section)
os->sectype_value = sectype_value;
else if (sectype == noload_section)
os->flags = SEC_NEVER_LOAD;
else
os->flags = SEC_NO_FLAGS;
os->block_value = 1;
/* Make next things chain into subchain of this. */
@ -8842,7 +8885,7 @@ lang_enter_overlay_section (const char *name)
etree_type *size;
lang_enter_output_section_statement (name, overlay_vma, overlay_section,
0, overlay_subalign, 0, 0, 0);
0, 0, overlay_subalign, 0, 0, 0);
/* If this is the first section, then base the VMA of future
sections on this one. This will work correctly even if `.' is

7
ld/ldlang.h

@ -122,7 +122,9 @@ enum section_type
overlay_section,
noload_section,
noalloc_section,
readonly_section
type_section,
readonly_section,
typed_readonly_section
};
/* This structure holds a list of program headers describing
@ -166,6 +168,7 @@ typedef struct lang_output_section_statement_struct
int constraint;
flagword flags;
enum section_type sectype;
etree_type *sectype_value;
unsigned int processed_vma : 1;
unsigned int processed_lma : 1;
unsigned int all_input_readonly : 1;
@ -545,7 +548,7 @@ extern void lang_add_output
(const char *, int from_script);
extern lang_output_section_statement_type *lang_enter_output_section_statement
(const char *, etree_type *, enum section_type, etree_type *, etree_type *,
etree_type *, int, int);
etree_type *, etree_type *, int, int);
extern void lang_final
(void);
extern void lang_relax_sections

1
ld/ldlex.l

@ -323,6 +323,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
<EXPRESSION>"DSECT" { RTOKEN(DSECT); }
<EXPRESSION>"COPY" { RTOKEN(COPY); }
<EXPRESSION>"INFO" { RTOKEN(INFO); }
<EXPRESSION>"TYPE" { RTOKEN(TYPE); }
<SCRIPT,EXPRESSION>"ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); }
<SCRIPT,EXPRESSION>"ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); }
<SCRIPT,EXPRESSION>"SPECIAL" { RTOKEN(SPECIAL); }

4
ld/mri.c

@ -210,8 +210,8 @@ mri_draw_tree (void)
base = p->vma ? p->vma : exp_nameop (NAME, ".");
lang_enter_output_section_statement (p->name, base,
p->ok_to_load ? normal_section : noload_section,
align, subalign, NULL, 0, 0);
p->ok_to_load ? normal_section : noload_section, 0,
align, subalign, NULL, 0, 0);
base = 0;
tmp = (struct wildcard_list *) xmalloc (sizeof *tmp);
tmp->next = NULL;

18
ld/testsuite/ld-scripts/output-section-types.d

@ -1,13 +1,17 @@
#ld: -Toutput-section-types.t
#source: align2a.s
#objdump: -h
#readelf: -S --wide
#target: [is_elf_format]
#...
. \.rom.*
[ ]+ALLOC, READONLY
. \.ro.*
[ ]+CONTENTS, ALLOC, LOAD, READONLY, DATA
. \.over.*
[ ]+CONTENTS, READONLY
.* .rom +NOBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
.* .ro +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
.* .over +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 + +0 +0 +[1248]
.* progbits +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
.* strtab +STRTAB +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
.* note +NOTE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
.* init_array +INIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248]
.* fini_array +FINI_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248]
.* preinit_array +PREINIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +0 +0 +[1248]
.* .ro.note +NOTE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +0 +0 +[1248]
#pass

7
ld/testsuite/ld-scripts/output-section-types.t

@ -2,6 +2,13 @@ SECTIONS {
.rom (NOLOAD) : { LONG(1234); }
.ro (READONLY) : { LONG(5678); }
.over (OVERLAY) : { LONG(0123); }
progbits (TYPE=SHT_PROGBITS) : { BYTE(1) }
strtab (TYPE = SHT_STRTAB) : { BYTE(0) }
note (TYPE =SHT_NOTE) : { BYTE(8) }
init_array (TYPE= 14) : { QUAD(14) }
fini_array ( TYPE=SHT_FINI_ARRAY) : { QUAD(15) }
preinit_array (TYPE=SHT_PREINIT_ARRAY ) : { QUAD(16) }
.ro.note (READONLY (TYPE=SHT_NOTE)) : { LONG(5678); }
/DISCARD/ : { *(*) }
}

Loading…
Cancel
Save