From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <3hy76YQcKCOIQEWOVEcKSSKPI.GSQFMRYXMPWWSYVGIaEVI.SVK@flex--maskray.bounces.google.com> Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by sourceware.org (Postfix) with ESMTPS id E10C53858437 for ; Wed, 2 Feb 2022 07:11:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E10C53858437 Received: by mail-yb1-xb49.google.com with SMTP id d65-20020a256844000000b00614359972a6so37519291ybc.16 for ; Tue, 01 Feb 2022 23:11:03 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=MIQBae+5PbwrYfEqX+WCh1dRSzVGJAJDeisvcOJTfbg=; b=Bu7ZBBitjd8ul4YxWn8/JdNZjJdnLpe+cADarxQJY5WPrrAaWOgdjG1wNI1Fn9i3CM MbSAH06BWRFxxkfSNuHEUjfF9l52NcGy//aBifYiOhoNe+mgVr/0JfaUgzU9xAAW405n QXzi31Thjg2851+BpXi+wN4BJ6YHWonIM2o+7F2RUJ5hxh7xSLjCGHn3p0haq9uTY7Br HOLV2PG5/SdZ8ElgxCaoJLUTqSf2bQBNbzJ84lZbj8mF8ho/78P6UeOOCOVluwLdIEtZ oLPNmoi4K5bmAYJQQ03B1Ga+B9mtcR+rL0JclvAxIbHvq6tiuR50zWLuJk+DHCUSAadp ikQg== X-Gm-Message-State: AOAM533nSO/oYumZljSV08i4c8BVuiTZPjiEg+UnuUwYfnZBBj2nJFCg flfKNSSNCpsh8l5VcdVtFH1U/5OlpVYLLTiTRgQ7thP5TPG53f4AbWekNHh7VFbiiDR4u9UKC1f BpDWGuR993UdiwE30NHHinRPFB1lmvosdvwVe3o5PomD+b9ceAJ4/e+pWg3+cDm9sAw== X-Google-Smtp-Source: ABdhPJx1h9Mept2s9jRIEPAc10ETQ+rkBU/NCJi0wDhYVUP/2OxxYoWbRpQ+6b3akfhIsAM+NkxEzzzTUSrR X-Received: from maskray1.svl.corp.google.com ([2620:15c:2ce:200:5421:fa79:d6f6:9a14]) (user=maskray job=sendgmr) by 2002:a81:7002:: with SMTP id l2mr531248ywc.213.1643785863320; Tue, 01 Feb 2022 23:11:03 -0800 (PST) Date: Tue, 1 Feb 2022 23:10:44 -0800 Message-Id: <20220202071044.1480421-1-maskray@google.com> Mime-Version: 1.0 Subject: [PATCH] ld: Support customized output section type From: Fangrui Song To: binutils@sourceware.org, Alan Modra , Nick Clifton Cc: Luca Boccassi , Fangrui Song Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-19.9 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, USER_IN_DEF_DKIM_WL autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: binutils@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Binutils mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 02 Feb 2022 07:11:05 -0000 The current output section type allows to set the ELF section type to SHT_PROGBITS or SHT_NOLOAD. This patch allows an arbitrary section value to be specified. Some ELF section type names are supported as well, e.g.: note (TYPE=SHT_NOTE) : { BYTE(8) } init_array (TYPE=14) : { BYTE(14) } fini_array (TYPE=SHT_FINI_ARRAY) : { BYTE(15) } 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. --- bfd/bfd-in2.h | 7 ++- bfd/elf.c | 4 +- bfd/section.c | 4 +- ld/ld.texi | 4 ++ ld/ldgram.y | 9 ++-- ld/ldlang.c | 49 ++++++++++++++++--- ld/ldlang.h | 4 +- ld/ldlex.l | 1 + ld/mri.c | 4 +- .../ld-scripts/output-section-types.d | 16 +++--- .../ld-scripts/output-section-types.t | 5 ++ 11 files changed, 82 insertions(+), 25 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 8e815bab624..91ec68d0391 100644 --- a/bfd/bfd-in2.h +++ b/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 \ \ } diff --git a/bfd/elf.c b/bfd/elf.c index 14c2c7ba734..1ebe7b425c4 100644 --- a/bfd/elf.c +++ b/bfd/elf.c @@ -3279,7 +3279,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); diff --git a/bfd/section.c b/bfd/section.c index 899438a1c5e..2de7dbf661a 100644 --- a/bfd/section.c +++ b/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 \ . \ . } . diff --git a/ld/ld.texi b/ld/ld.texi index fc75e9b3625..e3a1e02ed25 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -5490,6 +5490,10 @@ 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}. For the ELF output +file, some type names (e.g. @code{SHT_NOTE}) are also allowed for +@var{type}. @end table @kindex NOLOAD diff --git a/ld/ldgram.y b/ld/ldgram.y index 11c2f219c05..f5e3a834a26 100644 --- a/ld/ldgram.y +++ b/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 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 @@ -1131,7 +1132,7 @@ type: | INFO { sectype = noalloc_section; } | OVERLAY { sectype = noalloc_section; } | READONLY { sectype = readonly_section; } - ; + | TYPE '=' exp { sectype = type_section; sectype_value = $3; } atype: '(' type ')' diff --git a/ld/ldlang.c b/ld/ldlang.c index 5dd3df12a0f..a0a3c09f9a9 100644 --- a/ld/ldlang.c +++ b/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,6 +2635,7 @@ 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; @@ -4209,6 +4210,7 @@ map_input_to_output_sections { lang_output_section_statement_type *tos; flagword flags; + unsigned int type = 0; switch (s->header.type) { @@ -4261,6 +4263,37 @@ map_input_to_output_sections case noalloc_section: flags = SEC_HAS_CONTENTS; break; + 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_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 readonly_section: flags |= SEC_READONLY; break; @@ -4276,6 +4309,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; @@ -7564,6 +7598,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, @@ -7581,10 +7616,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) + 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. */ @@ -8901,7 +8938,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 diff --git a/ld/ldlang.h b/ld/ldlang.h index 0d057c9bee9..20b953eeac6 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -122,6 +122,7 @@ enum section_type overlay_section, noload_section, noalloc_section, + type_section, readonly_section }; @@ -166,6 +167,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 +547,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 diff --git a/ld/ldlex.l b/ld/ldlex.l index 78db16e3a48..c38b46b9336 100644 --- a/ld/ldlex.l +++ b/ld/ldlex.l @@ -323,6 +323,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)* "DSECT" { RTOKEN(DSECT); } "COPY" { RTOKEN(COPY); } "INFO" { RTOKEN(INFO); } +"TYPE" { RTOKEN(TYPE); } "ONLY_IF_RO" { RTOKEN(ONLY_IF_RO); } "ONLY_IF_RW" { RTOKEN(ONLY_IF_RW); } "SPECIAL" { RTOKEN(SPECIAL); } diff --git a/ld/mri.c b/ld/mri.c index b428ab0d0bf..5749870ef1e 100644 --- a/ld/mri.c +++ b/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; diff --git a/ld/testsuite/ld-scripts/output-section-types.d b/ld/testsuite/ld-scripts/output-section-types.d index ab124fa4dd7..56b88ce6342 100644 --- a/ld/testsuite/ld-scripts/output-section-types.d +++ b/ld/testsuite/ld-scripts/output-section-types.d @@ -1,13 +1,15 @@ #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-9] +0 +[1248] +.* .ro +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248] +.* .over +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 + +[0-9] +0 +[1248] +.* progbits +PROGBITS +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248] +.* note +NOTE +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +00 +A +[0-9] +0 +[1248] +.* init_array +INIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +[0-9] +0 +[1248] +.* fini_array +FINI_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +[0-9] +0 +[1248] +.* preinit_array +PREINIT_ARRAY +[0-9a-f]+ +[0-9a-f]+ +[0-9a-f]+ +0[48] +A +[0-9] +0 +[1248] #pass diff --git a/ld/testsuite/ld-scripts/output-section-types.t b/ld/testsuite/ld-scripts/output-section-types.t index d8fdfda1a03..834e5869d79 100644 --- a/ld/testsuite/ld-scripts/output-section-types.t +++ b/ld/testsuite/ld-scripts/output-section-types.t @@ -2,6 +2,11 @@ SECTIONS { .rom (NOLOAD) : { LONG(1234); } .ro (READONLY) : { LONG(5678); } .over (OVERLAY) : { LONG(0123); } + progbits (TYPE=SHT_PROGBITS) : { BYTE(1) } + note (TYPE=SHT_NOTE) : { BYTE(8) } + init_array (TYPE=14) : { BYTE(14) } + fini_array (TYPE=SHT_FINI_ARRAY) : { BYTE(15) } + preinit_array (TYPE=SHT_PREINIT_ARRAY) : { BYTE(16) } /DISCARD/ : { *(*) } } -- 2.35.0.rc2.247.g8bbb082509-goog