From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-f45.google.com (mail-pj1-f45.google.com [209.85.216.45]) by sourceware.org (Postfix) with ESMTPS id 2DCC33858C2C for ; Wed, 2 Feb 2022 18:32:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2DCC33858C2C Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=maskray.me Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pj1-f45.google.com with SMTP id p12-20020a17090a2d8c00b001b833dec394so382901pjd.0 for ; Wed, 02 Feb 2022 10:32:09 -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:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=SldaWE693Nkh89KUCk9Nj62ASQ42B4caKppvxg4FhC0=; b=hppmn6JmZau1p4PJma0N9e/PIqSvODjta5CUzMAG3BzzRLrwXo0DiOi4OVS1BQudN0 lOz75kKfmUShOCPscMC9iIEYZryIIJ1GRg6NfkJX4GkA7yKJ4zM577DIT8sgb2TfePiD TqSvZGmRcN+1C4OrHAEHEwaHK7BzUNbVx5LrtEIKia3tQz6EtkTYdaFVH4daKHz6yTG4 x4pPQA7MsKZKOndyw2Kb+JXGYZfBvkJFR6cgHKT0mdHFbNVzJnFUumvF8wpY1aOut1Up pZjOXBhyPKDV7yVjmyKPJsxQyOiXb+99/9cH7ab07xrGNBcwVW0RimnuQqQc2L6O2pGr AFDw== X-Gm-Message-State: AOAM530giEvhmpcMmYUBV9Y6EdCaaz7TrtoG0mggmqZ5FynSaoUtP4Pt pEGg19C6z5NbPX5ejmWMfFw= X-Google-Smtp-Source: ABdhPJzktN3deOvL3QWPbUPcviCSqhgtbpY+71nH08A0xWHjrG0NJLH0I3O3VSECE0xR+GcKu3tfIw== X-Received: by 2002:a17:902:ec84:: with SMTP id x4mr32098182plg.10.1643826728283; Wed, 02 Feb 2022 10:32:08 -0800 (PST) Received: from localhost ([2601:647:6300:b760:7aa8:4269:bb9c:ab3f]) by smtp.gmail.com with ESMTPSA id s9sm29418890pgm.76.2022.02.02.10.32.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Feb 2022 10:32:07 -0800 (PST) Date: Wed, 2 Feb 2022 10:32:06 -0800 From: Fangrui Song To: Nick Clifton Cc: Fangrui Song , binutils@sourceware.org, Alan Modra , Luca Boccassi Subject: Re: [PATCH] ld: Support customized output section type Message-ID: <20220202183206.fhnivs3kb4ntnkmp@gmail.com> References: <20220202071044.1480421-1-maskray@google.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="h5lluk67f7l5nakf" Content-Disposition: inline In-Reply-To: X-Spam-Status: No, score=-9.0 required=5.0 tests=BAYES_00, FREEMAIL_FORGED_FROMDOMAIN, FREEMAIL_FROM, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, KAM_INFOUSMEBIZ, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE 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 18:32:12 -0000 --h5lluk67f7l5nakf Content-Type: text/plain; charset=us-ascii; format=flowed Content-Disposition: inline On 2022-02-02, Nick Clifton via Binutils wrote: >Hi Fangrui, > >>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, > >Thanks for the patch submission. I am regression testing it at the moment >but in the meantime a couple of things stood out for me: > > >>+@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}. > >Rather than having users guess, it would probably be best to list which >type names are supported. > >Also it is probably worth documenting that it is the user's fault if they >set the section type to something which has special semantics (eg SHT_GROUP) >but then they do not also arrange for whatever necessary support that feature >needs. Something like: "it is the user's responsibility to ensure that >any special requirements of the section type are met". Thanks for the quick review! Adopted the wording and the change below. The new patch is in the attachment. For SHT_GROUP, I think it is useful to support SHT_GROUP as well. I actually did an experiment last night but SHT_GROUP led to an internal error. There may be some issues that need to be fixed to use the SHT_GROUP feature. > > >>+ 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); > >It might be worth adding SHT_STRTAB to this list, as I can imagine some >weird sceanario where someone would want it. Added. > >Also - given that this is a new feature, there really ought to be an entry >for it in the ld/NEWS file. Added. The NEW entry is for 2.39, but feel free to port it to 2.38 if you think appropriate:) >Cheers > Nick > --h5lluk67f7l5nakf Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="0001-ld-Support-customized-output-section-type.patch" >From 857ebfa9b7f905d747b689360be11d7f197b8ba5 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 2 Feb 2022 10:25:45 -0800 Subject: [PATCH] ld: Support customized output section type 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 ) : { QUAD(14) } fini_array (TYPE = SHT_FINI_ARRAY) : { QUAD(15) } It is the user's responsibility to ensure that any special requirements of the section type are met. Currently some section names are specially handled, e.g. a ".note" prefixed output section gets the type SHT_NOTE even if it contains no input section. This behavior may not be removed for backward compatibility, but it is recommended that new usage sets the type explicitly to cater to the ELF spirit that attributes are identified as well known integers instead of magic names. 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/NEWS | 3 ++ ld/ld.texi | 7 +++ ld/ldgram.y | 9 ++-- ld/ldlang.c | 51 ++++++++++++++++--- ld/ldlang.h | 4 +- ld/ldlex.l | 1 + ld/mri.c | 4 +- .../ld-scripts/output-section-types.d | 17 ++++--- .../ld-scripts/output-section-types.t | 6 +++ 12 files changed, 92 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/NEWS b/ld/NEWS index dbb402d1f8a..a498abaf0f9 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,8 @@ -*- text -*- +* 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 diff --git a/ld/ld.texi b/ld/ld.texi index fc75e9b3625..83c3ae8e6fd 100644 --- a/ld/ld.texi +++ b/ld/ld.texi @@ -5490,6 +5490,13 @@ 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_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. @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..62ca0c9d059 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,39 @@ 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_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 readonly_section: flags |= SEC_READONLY; break; @@ -4276,6 +4311,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 +7600,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 +7618,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 +8940,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..214b1cf6e58 100644 --- a/ld/testsuite/ld-scripts/output-section-types.d +++ b/ld/testsuite/ld-scripts/output-section-types.d @@ -1,13 +1,16 @@ #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] #pass diff --git a/ld/testsuite/ld-scripts/output-section-types.t b/ld/testsuite/ld-scripts/output-section-types.t index d8fdfda1a03..4fd498c9ba0 100644 --- a/ld/testsuite/ld-scripts/output-section-types.t +++ b/ld/testsuite/ld-scripts/output-section-types.t @@ -2,6 +2,12 @@ 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) } /DISCARD/ : { *(*) } } -- 2.35.0.rc2.247.g8bbb082509-goog --h5lluk67f7l5nakf--