From patchwork Fri Nov 29 10:12:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Lyon X-Patchwork-Id: 180483 Delivered-To: patch@linaro.org Received: by 2002:a92:3001:0:0:0:0:0 with SMTP id x1csp1307753ile; Fri, 29 Nov 2019 02:12:46 -0800 (PST) X-Google-Smtp-Source: APXvYqydVSQM94lhUPtZ2nX/1qrsAlQiK4f/+D+PKcmSrqUm9BKwmiaU5gP4NEFqCt698XT0CY5s X-Received: by 2002:aa7:c1cd:: with SMTP id d13mr18741951edp.288.1575022365866; Fri, 29 Nov 2019 02:12:45 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1575022365; cv=none; d=google.com; s=arc-20160816; b=B+WTfoTvceEzczdXqK9El4j1G1tIxHBZW9nwVBu/a5cJHP+/p0OnedhjFBx9GFEM0l /zybG5jM143LXcS+67vlvIrw53NmfC7R+0yRHJAoWdsZGY3xvKJ+dCy/66CMgNmEyN73 4E+jsunjh3mFU7G55YMBGIju/NOfjUDF+ljb0t7DCvQoDHXHIyZiT+6b08PwqXshAxTu OrKEKUVBXoiABQI8r+FuAMrUfZO41U9+16BWSkh6Iv3znxtDtoeygqFdC7bQvn0PD1G9 dSqm7YWpIx2DsCjb8216pxYg8t42Ampyohnrkb7LjNpl58m6SHB7d21vgi1Um6LigR7J w+EQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=to:subject:message-id:date:from:mime-version:dkim-signature :delivered-to:sender:list-help:list-post:list-archive:list-subscribe :list-unsubscribe:list-id:precedence:mailing-list:dkim-signature :domainkey-signature; bh=f2neSuU58CltTh7mVix8s3xADAz8EYAzQkBx9+3ssEc=; b=X7ob7eNm8sucKSAS+mwaCtgLxGxZAlD0O9Iub54Pf53rxbWBq+JIcBOWmkiekRQ2RI MURQ+wVuey9DlRvlBGbq8d1lwyVsnd+Ecwap4xPbjQT3OUOit40Nlbjcr/WPOv+HQu0H DCFOEdSwZsGA/zsa9xLMzIsrYYRU5zeSfZdlrvGowahskAU+N43xhdJXTQar5wyyVmEe UNm45phbkSwc1nZGFoEyYR5E2DPWEKuOWNTIYUYVu8Xr2Uwph8nFxCJxy2FKS99+c9BT YPk1+3I6EAsOE/vaktTnnII97JR00k+wM202TbP6EcSvCLYOjzzYUynVnkZbFC2gmAT7 DS+g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=Z1POQsiX; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b="QNXulk/q"; spf=pass (google.com: domain of binutils-return-107760-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="binutils-return-107760-patch=linaro.org@sourceware.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id d27si5542487edj.136.2019.11.29.02.12.44 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 29 Nov 2019 02:12:45 -0800 (PST) Received-SPF: pass (google.com: domain of binutils-return-107760-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@sourceware.org header.s=default header.b=Z1POQsiX; dkim=neutral (body hash did not verify) header.i=@linaro.org header.s=google header.b="QNXulk/q"; spf=pass (google.com: domain of binutils-return-107760-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom="binutils-return-107760-patch=linaro.org@sourceware.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:from:date:message-id:subject:to :content-type; q=dns; s=default; b=Pf94voNVEdFY9ZIEkNUe7rRzSM25U rstjbxP7ERCadl7DQfkXuw5u8M3ILKn9Et5vN00oLOB4ypydOvPb9Fwl8OHIhocu VE7ifgZxcQyWkucJpKgS/tcAFDeti8rfKFhYq4KblDvFL5YU6/SWL57fSVNVPiBE vw0JlAXOCrDcLU= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:mime-version:from:date:message-id:subject:to :content-type; s=default; bh=9QZ+J5Qo5qWyUTZnQCf7twqdF8c=; b=Z1P OQsiXu33af6BJztm3mf+qAGFyCE/SEPv+0YZaljHGh/cIaT1CiUfsLDSkUpuVc32 UqqP3oh/PraOT924rWt5zVW3ZrqS5OEiktSQV/qDEuCnK8ibN1GbNx0XKwpuDikJ pXRjEqFm8HX30hP5SDSTUgROuKZU7NApRm2n30Lw= Received: (qmail 106511 invoked by alias); 29 Nov 2019 10:12:21 -0000 Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org Delivered-To: mailing list binutils@sourceware.org Received: (qmail 106441 invoked by uid 89); 29 Nov 2019 10:12:20 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-16.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=forcing, 5016, boot, ORIGIN X-HELO: mail-lj1-f178.google.com Received: from mail-lj1-f178.google.com (HELO mail-lj1-f178.google.com) (209.85.208.178) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 29 Nov 2019 10:12:17 +0000 Received: by mail-lj1-f178.google.com with SMTP id m4so31339201ljj.8 for ; Fri, 29 Nov 2019 02:12:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:from:date:message-id:subject:to; bh=piJE8AZKNtBvK+2cYK03gvYEt2YXP1IAOpnUDhEWEG8=; b=QNXulk/q3wCXIWouAK3a91xzB6XHjKKf7jDor7ZdihXwMFbTqgI/DtA/efGhelRNf1 XjtYb3F1uuYweusQHCRXwDatISq5t5ZQEcpAKoFNvOkWYLzDyHi4GZg7H4v4dt14IQEQ EPMFCwi9B0p0Ud7X6kZtgPiM2iqgLve8Td4cMjW7tT3w5m8r76z05o5erDOpiBNCf6Vl /tk4rDAEuyuJc40h+mItLeTkEiA19NAqaUP6X1juyA6ufrsZJwdWiybqfXLkooj4pLfq l4UDOWT0LiKumXI5tnkeLrQ1h6Fp1LQ5rfuBb7wfRaa3Y6grJ+ycYmR76thWh/rVhqs7 U6gA== MIME-Version: 1.0 From: Christophe Lyon Date: Fri, 29 Nov 2019 11:12:03 +0100 Message-ID: Subject: [PATCH RFC] Add support for non-contiguous memory regions To: binutils X-IsSubscribed: yes Hi, The attached patches implement support for non-contiguous memory regions, which was discussed in more detail in https://sourceware.org/ml/binutils/2019-07/msg00020.html In other words, it allows to list input sections in multiple output regions, to help with cases were we have several memory banks, but don't care in which one a given section goes. This avoids the painful linker script changes needed when a memory banks become too small after program changes (eg more data, or compiler code generation changes). Patch 1 contains the implementation, and patch 2 adds a new test. This is an RFC because it lacks documentation, and I thought I should check whether the approach is OK before polishing. Patch 1 adds a new --enable-non-contiguous-regions linker flag which is required to enable this new feature. Of course, we can discuss the option name, suggestions welcome :-) It works by allowing processing of input section multiple times until a sufficiently large output region is found, the irrelevant ones are removed when we detect that the candidate input section would overflow the current output section. At some point I thought I should insert padding when an input section is too large to fit in the current output section, in order to make sure it is full, but it turns out not to be necessary. The added testcase defines 4 input sections: .data, .data.2, .data.3 and .data.4, and the linker script has *(.data) *(.data.*) for each of the 3 output sections .raml, .ramu and .ramz. .data.3 and .data.3 do not fit in .raml, and are thus assigned respectively to .ramu and .ramz. I've run the tests with arm-none-eabi as target, and also checked that there is no regression when forcing --enable-non-contiguous-regions: actually only the ld/scripts/rgn-over* tests fail in such a case, because the offending sections can be assigned to other large enough output sections, and we no longer face the error cases these tests try to catch. One bit I'm not clear about in the expected results is the file offset for .ramu and .ramz sections: why are they aligned on 0x1000, while .ARM.attributes isn't ? In fact, I feel my patch is surprisingly small for a feature that has been requested for so long... :-) Thoughts? Thanks, Christophe >From 5a6274a0db009b7e19835a0726c88360d9b9c6e8 Mon Sep 17 00:00:00 2001 From: Christophe Lyon Date: Mon, 25 Nov 2019 08:55:37 +0000 Subject: [PATCH 1/2] Add support for non-contiguous memory 2019-11-27 Christophe Lyon bfd/ * bfd-in2.h: Regenerate. * section.c (asection): Add already_assigned field. (BFD_FAKE_SECTION): Add default initializer for it. include/ * bfdlink.h (bfd_link_info): Add non_contiguous_regions field. ld/ * ldlang.c (lang_add_section): Add support for non_contiguous_regions. (size_input_section): Likewise. (lang_size_sections_1): Likewise. * ldlex.h (option_values): Add OPTION_NON_CONTIGUOUS_REGIONS. * lexsup.c (ld_options): Add entry for --enable-non-contiguous-regions. (parse_args): Handle it. --- bfd/bfd-in2.h | 9 +++++++- bfd/section.c | 9 +++++++- include/bfdlink.h | 3 +++ ld/ldlang.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++--- ld/ldlex.h | 1 + ld/lexsup.c | 5 +++++ 6 files changed, 89 insertions(+), 5 deletions(-) diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index a00dfa35..0e1126c 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -1177,6 +1177,10 @@ typedef struct bfd_section struct bfd_link_order *link_order; struct bfd_section *s; } map_head, map_tail; + /* Points to the output section this section is already assigned to, if any. + This is used when support for non-contiguous memory regions is enabled. */ + struct bfd_section *already_assigned; + } asection; /* Relax table contains information about instructions which can @@ -1358,7 +1362,10 @@ discarded_section (const asection *sec) (struct bfd_symbol *) SYM, &SEC.symbol, \ \ /* map_head, map_tail */ \ - { NULL }, { NULL } \ + { NULL }, { NULL }, \ + \ + /* already_assigned */ \ + NULL \ } /* We use a macro to initialize the static asymbol structures because diff --git a/bfd/section.c b/bfd/section.c index 34e08ae..b1f0b71 100644 --- a/bfd/section.c +++ b/bfd/section.c @@ -536,6 +536,10 @@ CODE_FRAGMENT . struct bfd_link_order *link_order; . struct bfd_section *s; . } map_head, map_tail; +. {* Points to the output section this section is already assigned to, if any. +. This is used when support for non-contiguous memory regions is enabled. *} +. struct bfd_section *already_assigned; +. .} asection; . .{* Relax table contains information about instructions which can @@ -717,7 +721,10 @@ CODE_FRAGMENT . (struct bfd_symbol *) SYM, &SEC.symbol, \ . \ . {* map_head, map_tail *} \ -. { NULL }, { NULL } \ +. { NULL }, { NULL }, \ +. \ +. {* already_assigned *} \ +. NULL \ . } . .{* We use a macro to initialize the static asymbol structures because diff --git a/include/bfdlink.h b/include/bfdlink.h index 32d1512..e1e7c1e 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -501,6 +501,9 @@ struct bfd_link_info /* TRUE if "-Map map" is passed to linker. */ unsigned int has_map_file : 1; + /* TRUE if "--enable-non-contiguous-regions" is passed to the linker. */ + unsigned int non_contiguous_regions : 1; + /* Char that may appear as the first char of a symbol, but should be skipped (like symbol_leading_char) when looking up symbols in wrap_hash. Used by PowerPC Linux for 'dot' symbols. */ diff --git a/ld/ldlang.c b/ld/ldlang.c index eedcb7f..f2acdbb 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -2550,7 +2550,14 @@ lang_add_section (lang_statement_list_type *ptr, } if (section->output_section != NULL) - return; + { + if (!link_info.non_contiguous_regions) + return; + /* SECTION has already been affected to an output section, but + the user allows it to be mapped to another one in case it + overflows. We'll later update the actual output section in + size_input_section as appropriate. */ + } /* We don't copy the SEC_NEVER_LOAD flag from an input section to an output section, because we want to be able to include a @@ -5109,11 +5116,27 @@ size_input_section (lang_statement_union_type **this_ptr, lang_output_section_statement_type *output_section_statement, fill_type *fill, + bfd_boolean *removed, bfd_vma dot) { lang_input_section_type *is = &((*this_ptr)->input_section); asection *i = is->section; asection *o = output_section_statement->bfd_section; + *removed = 0; + + if (link_info.non_contiguous_regions) + { + /* If the input section I has already been successfully assigned + to an output section other than O, don't bother with it and + let the caller remove it from the list. Keep processing in + case we have already handled O, because the repeated passes + have reinitialized its size. */ + if (i->already_assigned && i->already_assigned != o) + { + *removed = 1; + return dot; + } + } if (i->sec_info_type == SEC_INFO_TYPE_JUST_SYMS) i->output_offset = i->vma - o->vma; @@ -5145,6 +5168,24 @@ size_input_section dot += alignment_needed; } + if (link_info.non_contiguous_regions) + { + /* If I would overflow O, let the caller remove I from the + list. */ + if (output_section_statement->region) + { + bfd_vma end = output_section_statement->region->origin + + output_section_statement->region->length; + + if (dot + TO_ADDR (i->size) > end) + { + *removed = 1; + dot = end; + return dot; + } + } + } + /* Remember where in the output section this input section goes. */ i->output_offset = dot - o->vma; @@ -5152,6 +5193,14 @@ size_input_section dot += TO_ADDR (i->size); if (!(o->flags & SEC_FIXED_SIZE)) o->size = TO_SIZE (dot - o->vma); + + if (link_info.non_contiguous_regions) + { + /* Record that I was successfully assigned to O, and update + its actual output section too. */ + i->already_assigned = o; + i->output_section = o; + } } return dot; @@ -5436,9 +5485,10 @@ lang_size_sections_1 bfd_boolean check_regions) { lang_statement_union_type *s; + lang_statement_union_type *prev_s = NULL; /* Size up the sections from their constituent parts. */ - for (s = *prev; s != NULL; s = s->header.next) + for (s = *prev; s != NULL; prev_s = s, s = s->header.next) { switch (s->header.type) { @@ -5852,6 +5902,7 @@ lang_size_sections_1 case lang_input_section_enum: { asection *i; + bfd_boolean removed; i = s->input_section.section; if (relax) @@ -5864,7 +5915,17 @@ lang_size_sections_1 *relax = TRUE; } dot = size_input_section (prev, output_section_statement, - fill, dot); + fill, &removed, dot); + + if (link_info.non_contiguous_regions && removed) + { + /* If I doesn't fit in the current output section, + remove it from the list. */ + if (prev_s) + prev_s->header.next=s->header.next; + else + *prev = s->header.next; + } } break; diff --git a/ld/ldlex.h b/ld/ldlex.h index 32a7a64..4e7a419 100644 --- a/ld/ldlex.h +++ b/ld/ldlex.h @@ -150,6 +150,7 @@ enum option_values OPTION_FORCE_GROUP_ALLOCATION, OPTION_PRINT_MAP_DISCARDED, OPTION_NO_PRINT_MAP_DISCARDED, + OPTION_NON_CONTIGUOUS_REGIONS, }; /* The initial parser states. */ diff --git a/ld/lexsup.c b/ld/lexsup.c index d7766c3..13cab6d 100644 --- a/ld/lexsup.c +++ b/ld/lexsup.c @@ -122,6 +122,8 @@ static const struct ld_option ld_options[] = 'E', NULL, N_("Export all dynamic symbols"), TWO_DASHES }, { {"no-export-dynamic", no_argument, NULL, OPTION_NO_EXPORT_DYNAMIC}, '\0', NULL, N_("Undo the effect of --export-dynamic"), TWO_DASHES }, + { {"enable-non-contiguous-regions", no_argument, NULL, OPTION_NON_CONTIGUOUS_REGIONS}, + '\0', NULL, N_("Enable support of non-contiguous memory regions"), TWO_DASHES }, { {"EB", no_argument, NULL, OPTION_EB}, '\0', NULL, N_("Link big-endian objects"), ONE_DASH }, { {"EL", no_argument, NULL, OPTION_EL}, @@ -845,6 +847,9 @@ parse_args (unsigned argc, char **argv) case OPTION_NO_EXPORT_DYNAMIC: link_info.export_dynamic = FALSE; break; + case OPTION_NON_CONTIGUOUS_REGIONS: + link_info.non_contiguous_regions = TRUE; + break; case 'e': lang_add_entry (optarg, TRUE); break; -- 2.7.4