From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wm1-x32e.google.com (mail-wm1-x32e.google.com [IPv6:2a00:1450:4864:20::32e]) by sourceware.org (Postfix) with ESMTPS id 2C2193858012 for ; Fri, 23 Oct 2020 10:20:20 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2C2193858012 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wm1-x32e.google.com with SMTP id l15so922186wmi.3 for ; Fri, 23 Oct 2020 03:20:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:references:mime-version :content-disposition:in-reply-to; bh=BBuvtY2OYlfJtjV43xjhNjIxkh4/wBd5CzwcA+UT98o=; b=k5chp6/I9Xm2DpZptd0MBmy2wz2AK3yH0bXZd9GTeVEHVyv3eo48J9K+XIGKv1F+Zt mgbDvud3wsWupy37njrGgt5FTNjgw4B0zn7/gh8oLliYylrmiqm8NVYGhM77PmMtf4Xk FdyLkdJU24CC8gtPY6xzCnGsdiopVOWTZU4btAusdjYd575JIq2hokRnc9Q6eZ14rvkU Zzg1GcHILuntSi5HZN1lgUl9UH29FCE/gik/QKWyJ4soNcRTEALKkTHjFsL2P5t6Kv5u sITdxIpk09yvIoe2bcGj8VCfAFnwUA1ONe2G10A2Pe3AzUWf62SuZ6cqkbVkg2Le7wSI H9Rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=BBuvtY2OYlfJtjV43xjhNjIxkh4/wBd5CzwcA+UT98o=; b=nKO/A9zmK2upn4JCIKsbMENwAcGn7NGjb41A4j/8TnGupzBTSIAUNJKUI9JV97p2BU 6tPWnC5TmWYz8QoUYVum0+Amm0Bl3Grme6e7e0pdiMxEW+O7DjfAI157cbkscfxCeJoo 7jPBFc5jMa6ZctetmVRVYhQ8D45bi8PwKwi6QVP0E0MZvHdZ36mWHM9P2t42RnyiMRew 97I++9+U5PgTfzHcz60wztOUW3e2p006Z0ov05NJhRxH4zczJyDmh3/M1NohqilGu6sT Ol2UZErGayWkFjqoUWvGCQgSnnY6HTqzPDZaEDGUul4StuuB/z1s4Trz2E72fghOyn5l oy/A== X-Gm-Message-State: AOAM533cSst0yHuwkpEWdY2JmF33f82rkVDUl9PmSpKzs2d0zApKd7TM WlffYGqq4KcnqOEpYQ6BESPp1tpQCFK14hXl X-Google-Smtp-Source: ABdhPJxF/4dSqSX8fWpY0ZKzHtxIRTXZ+5N91Pq/8BUlAZDIRI/MXV+H4Ak9nusRZNtvjNCj0nyytw== X-Received: by 2002:a1c:2096:: with SMTP id g144mr1630283wmg.79.1603448418043; Fri, 23 Oct 2020 03:20:18 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id t5sm2783030wrb.21.2020.10.23.03.20.17 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Oct 2020 03:20:17 -0700 (PDT) Date: Fri, 23 Oct 2020 11:20:16 +0100 From: Jozef Lawrynowicz To: gnu-gabi@sourceware.org Subject: Re: [RFC] SHF_GNU_ABIND Section Flag Message-ID: <20201023102016.xf7emonkvil3dcay@jozef-acer-manjaro> References: <20201020100557.es5dsamudddio2kk@jozef-acer-manjaro> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20201020100557.es5dsamudddio2kk@jozef-acer-manjaro> X-Spam-Status: No, score=-11.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gnu-gabi@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gnu-gabi mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 23 Oct 2020 10:20:29 -0000 On Tue, Oct 20, 2020 at 11:05:57AM +0100, Jozef Lawrynowicz wrote: > Hi, > > I'd like to propose a new section flag, SHF_GNU_ABIND. > > The flag allows the virtual memory address of a section to be specified > within relocatable files, in advance of the final link. When linking > executable files, the linker will try to place sections marked with > SHF_GNU_ABIND at the address specified by their sh_addr field. > > "ABIND" is short for "address bind", used to indicate that the > section is "bound" to a specific address at run time. > > I've attached a Binutils patch that implements SHF_GNU_ABIND. > > I look forward to hearing your thoughts, > Jozef Does anyone have any comments on this proposal? I was in two minds about including the .gnu.abind_init_array stuff, it is probably superfluous as it is not required for the main use cases of SHF_GNU_ABIND, so I think I will remove it. Most targets would not require it at all. Removing it will greatly simplify the proposal and keep any ABI modifications to a minimum. The real use cases for SHF_GNU_ABIND do not have to be concerned with the case where LMA != VMA for the section being placed. Since they are normally making use of a feature of the hardware located at that address, that area of memory will be directly loadable. The issue of .bss sections being placed outside the the block of memory that is automatically initialized to zero by the startup code is easily worked around by forcing the compiler to emit any zero initialized or uninitialized data into a .data SHT_PROGBITS section. Targets that want to support placement of LMA != VMA sections can implement their own mechanism for handling it, as required. Meanwhile the linker will just error if it encounters a GNU_ABIND section that requires LMA != VMA. So the only ABI changes would be to support the new section flag itself, as defined below. If there ends up being some need for standardization of .gnu.abind_init_array-like functionality, there is no reason that can't be added later. Thanks, Jozef > > =========================================================== > ----------------------- > Section Attribute Flags > ----------------------- > +-------------------------------------+ > | Name | Value | > +-------------------------------------+ > | SHF_GNU_ABIND | 0x400000 (1 << 22) | > +-------------------------------------+ > > SHF_GNU_ABIND > The sh_addr field describes the virtual address at which > the first byte of the section should reside at in memory. > > =========================================================== > > Outline: > - Motivation > - Placement using linker script > - ABI details for SHF_GNU_ABIND runtime initialization > - Implementation > - Alternative Method to Implement the "location" attribute > - Conclusion > - Appendix - Examples > > ---------- > Motivation > ---------- > Placement of function or variable declarations at specific addresses can > be useful in a variety of situations. > > Many processors have areas of the memory map with special properties. > The data stored in these areas may be treated by the hardware in > some unique way. > For example: > - Slots in an interrupt vector table > When an interrupt triggers, the processor will read the address of the > associated interrupt service routine from a particular address within > the vector table. > - Memory-mapped peripheral registers > To check the status, or modify the behavior, of peripherals, control > registers are defined at specific addresses and can be read from, or > written to. > > Programmers may also find it useful to store information at a > memorable address. Perhaps some data is shared between a bootloader and > the application itself, stored in a common area of memory. > > The requirement for SHF_GNU_ABIND is motivated by a broader proposal for > a new attribute, "location", which can be set on function and variable > declarations in the source code. > This attribute will enable a declaration to be placed at a specific > virtual address, and SHF_GNU_ABIND is used to convey this requirement in > relocatable files. > > Similar attributes are implemented in other toolchains, such as ARM > Keil's "at" attribute, and the "location" attribute implemented in TI > toolchains across a variety of their processors. > > ----------------------------- > Placement using linker script > ----------------------------- > To place a declaration of a function or variable at a specific address, > the programmer must currently make modifications to the linker script. > Linker script modifications for this are cumbersome, and must be coupled > with modifications to the source code that place the declaration in a > specific section. > > The programmer has to: > - Apply the "section" attribute to the declaration they want to place > at a specific address, so it gets placed in a uniquely named section. > - Modify the linker script, creating a new output section with > the desired VMA for the declaration, containing a rule to match the > section they created for the declaration in the source code. > > However, there are some potential pitfalls the programmer can fall into > when making linker script modifications to place their section at > a specific address: > - The programmer may not consider the best position to put their new > output section within the list of output sections. > In a linker script with multiple output sections, a sub-optimal > decision about which sections they will place their new section > between could result in large, empty gaps in their executable file. > This limits the space available for their application, possibly > resulting in the program failing to link, or heap/stack availability > being low. > * With SHF_GNU_ABIND, the optimal position of the new output section > within the statement list can be automatically calculated. > - The programmer may not consider whether an LMA region needs to be set > for their new output section, if their desired address is within a > non-loadable memory region. > * With SHF_GNU_ABIND, the linker automatically decides if a separate > LMA region is required and sets the load address accordingly. > > There are additional generic benefits to avoiding linker script > modifications: > - The requirement for placement of a declaration at a specific address > may be application-specific, so consolidating this requirement to be > contained entirely within the source code improves portability. > - Generally avoiding linker script modifications can improve the user > experience, when the programmer is inexperienced with the linker > script format. The boilerplate linker script code required for > standard application operation can make modifications error-prone and > have unintended side-effects. > > Furthermore, with SHF_GNU_ABIND, the number of individual changes > required to achieve placement at a specific address is reduced. > > With linker script modifications: > *.ld: > | SECTIONS > | { > | ... other sections ... > | my_decl 0x1000 : { *(.data.my_decl_at_0x1000) } > | ... other sections ... > | } > *.c: > | int __attribute__((section(".data.my_decl_at_0x1000"))) = 0xABCD; > > With SHF_GNU_ABIND and the "location" attribute: > *.c: > | int __attribute__((location(0x1000))) = 0xABCD; > > Following are some further ABI details, describing the implementation > required to support placement of sections with LMA not equal to VMA, and > sections consisting of zero-initialized data. > > ================================================================ > ---------------- > Special Sections > ---------------- > .gnu.abind_init_array > This section holds an array of ElfXX_AbindInitArray_Entry entries, > which describe how to initialize the contents of SHF_GNU_ABIND > sections at runtime, for sections that require runtime initialization. > See "SHF_GNU_ABIND Section Initialization" for more details. > > ------------------------------------ > SHF_GNU_ABIND Section Initialization > ------------------------------------ > Some SHF_GNU_ABIND sections will require initialization at runtime. The > conditions for the initialization requirement are: > - The program will run on a ROM based system, so SHF_GNU_ABIND sections > with their virtual memory address (VMA) specified in a non-loadable > memory region require their contents to be copied from their load > memory address (LMA) to their VMA during program initialization. > - The SHF_GNU_ABIND section has type SHT_NOBITS and would have been > placed in a .bss output section, and its contents set to zero during > program initialization. The specified VMA for the SHF_GNU_ABIND > section may not be within the bounds of the zero-initialized block of > other .bss sections, so the section will require it's contents to be > explicitly set to zero at runtime. For targets that do not zero .bss, > this is not required. > > For devices without non-loadable memory regions, and so will not have > any sections with LMA not equal to VMA, it is possible to avoid the need > for .gnu.abind_init_array. > Defining any SHF_GNU_ABIND sections containing zero-initialized data > explicitly as an SHT_PROGBITS ".data" section and initializing its > contents to 0 will ensure the program loader sets its contents to 0, > rather than relying on the application to zero it. > .gnu.abind_init_array will therefore not be required in this case. > If the compiler handles this automatically, .gnu.abind_init_array > support could be entirely omitted for the target. > > The "__run_gnu_abind_init_array" function performs runtime > initialization of SHF_GNU_ABIND sections that require it, as described > by .gnu.abind_init_array entries. > > If .gnu.abind_init_array will be present in the executable file and has > non-zero size, an entry for __run_gnu_abind_init_array must be placed in > the ".init_array" section. > > ----------------------------- > .gnu.abind_init_array Entries > ----------------------------- > typedef struct > { > Elf32_Addr vma; > Elf32_Addr lma; > Elf32_Word size; > } Elf32_AbindInitArray_Entry; > > typedef struct > { > Elf64_Addr vma; > Elf64_Addr lma; > Elf64_Xword size; > } Elf64_AbindInitArray_Entry; > > The bounds of .gnu.abind_init_array are described by the following > symbols: > __gnu_abind_init_array_start > __gnu_abind_init_array_end > > To initialize the sections, __run_gnu_abind_init_array has a choice for > each entry: > - When lma != vma, copy "size" bytes from address "lma" to address > "vma". > - When lma == vma, this is an SHT_NOBITS section requiring > zero-initialization. Set "size" bytes starting from address "vma" to > 0. > > A sample implementation of __run_gnu_abind_init_array for a 32-bit > target is shown below: > > void > __run_gnu_abind_init_array (void) > { > void *ptr; > for (ptr = &__gnu_abind_init_array_start; > ptr != &__gnu_abind_init_array_end; > ptr += sizeof (Elf32_AbindInitArray_Entry)) > { > Elf32_AbindInitArray_Entry *ent = ptr; > > if (ent->lma != ent->vma) > __builtin_memcpy (ent->vma, ent->lma, ent->size); > else > __builtin_memset (ent->vma, 0, ent->size); > } > } > ================================================================ > -------------- > Implementation > -------------- > GCC supports a new "location" attribute, which can be applied to > function and variable declarations. The argument to the "location" > attribute indicates the virtual memory address that the declaration > should be placed at. > > int __attribute__((location(0x5000))) checksum = 0xABCD; > > GCC will place the declaration that the "location" attribute is applied > to in its own, uniquely named section. GCC will then describe the > requirement for placement at a specific address to the assembler. > > For systems which do not have any non-loadable memory regions, GCC can > modify the type and name created for zero-initialized data. Placing this > data in an SHT_PROGBITS section with the ".data" prefix, instead of an > SHT_NOBITS sections with the ".bss" prefix, and explicitly initializing > its contents to 0 will avoid the need for any runtime support for > SHF_GNU_ABIND via .gnu.abind_init_array. > > GAS supports a new flag value "A" to the "flags" argument of the > .section directive. The specified address is read from the > "flag_specific_arguments" argument to .section. > > .section .data.checksum,"awA",0x5000 > > GAS will set the SHF_GNU_ABIND flag on the section, and the sh_addr > field to the specified address. > > When loading object files to link an executable file, LD will "orphan" > SHF_GNU_ABIND sections by renaming them, giving them the ".gnu.abind" > prefix. This means they won't match any input section rules from the > linker script. The "orphaned" SHF_GNU_ABIND input sections will now have > their own output sections, which can be placed freely at the address > specified by the sh_addr field of the corresponding input section. > > -------------------------------------------------------- > Alternative Method to Implement the "location" attribute > -------------------------------------------------------- > An alternative method of conveying the requirement for placement of a > section at a specific address, from the compiler to the linker, would be > for the compiler to set a specific section name which captures both the > status of the section as one requiring placement, and the address it > should be placed at. > > For example: > int __attribute__((location(0x5000))) checksum = 0xABCD; > becomes > .section .gnu_location_0x5000.data.checksum,"aw" > > In theory, the assembler and linker implementation does not need to be > very different from what is required for SHF_GNU_ABIND, as these > programs can set an internal flag on sections which have the > .gnu_location prefix to treat them in a special way. > > However, the additional prefix for the section on entry to the assembler > and linker might interfere with some common behavior. > > It is also not standard to convey information about a section > in the name. This method should only be used if the proposed ABI > modifications cannot be made for some reason. > Additionally, it would result in the loss of opportunity for > standardization of .gnu.abind_init_array and associated runtime > functionality. > > ---------- > Conclusion > ---------- > The "location" attribute, making use of SHF_GNU_ABIND, will improve the > user experience and simplify development for programmers wishing to make > use of the functionality to place function and variable declarations at > specific addresses. The behavior can now be implemented in fewer steps, > and without leaving the source code. Cumbersome and error-prone linker > script modifications are avoided. > > For embedded devices, maintenance of board support packages is eased, as > many hardware features that had to be described in both header file and > linker scripts, with the corresponding definitions requiring precise > alignment between the files, now require specification only in header > files. > > Applications are more portable, as those which require declarations to > be placed at a specific address can now be entirely described from the > source code, without requiring an accompanying linker script. > > ------------------- > Appendix - Examples > ------------------- > Below are some examples for the "location" attribute in real use cases. > > Mapping a Structure over Memory-mapped Peripheral Registers > --------------------------------------------------------- > Current methods for accessing memory-mapped registers are: > - Set the address of a structure at runtime, in application code. > * Requires additional code to setup the address of the structure > before registers can be accessed. > - Use a symbolic reference to the registers, defined in header files but > resolved at link time. > * Requires implementation in both header file and linker scripts. > > The "location" attribute allows consolidation of this information > entirely within the source code, and without any runtime initialization > required. > > typedef struct > { > char regA; > char regB; > char ctrl; > } peripheral_reg; > > peripheral_reg __attribute__((location(0x65000))) pregs1; > > /* Above code can be hidden in a header file from a board support > package for a particular device. */ > > void > manip_regs (void) > { > pregs1.ctrl = 1; /* MOV #1, &0x65002 */ > pregs1.regA = 10; /* MOV #10, &0x65000 */ > pregs1.regB = 20; /* MOV #20, &0x65001 */ > pregs1.ctrl = 0; /* MOV #0, &0x65002 */ > } > > Placement in the Interrupt Vector Table > --------------------------------------- > Implementation of interrupt vectors currently requires explicit support > between the source code and linker script: > > SECTIONS > { > __ivec_rtc 0xFF00 : { KEEP (*(__ivec_rtc)) } > } > > /* "interrupt" attribute is required to create the "__ivec_rtc" > section and place the address of "isr_rtc" within it. */ > void __attribute__((interrupt("rtc")) > isr_rtc (void) > { > clock_var++; > } > > The name of the interrupt service routine must be aligned between the > source code, compiler (a hard-coded prefix must be added) and the linker > script. > > The "location" attribute, used in conjunction with "retain" greatly > simplifies the procedure, and does not require any linker script > modifications. > > /* If a board support package is available, refer to the address > symbolically. */ > #ifdef __BSP__ > static void * __attribute__((retain,location(VEC_RTC))) > #else > static void * __attribute__((retain,location(0xFF00))) > #endif > __ivec_rtc = isr_rtc; > > void > isr_rtc (void) > { > clock_var++; > } > > As an extension to the proposal, a new "interrupt_loc" attribute could > emit section declarations for vector table slots, setting SHF_GNU_RETAIN > and SHF_GNU_ABIND on the section. This would allow an ISR to be > completely specified with only a function declaration and possibly an > associated definition from a header file. > > #ifdef __BSP__ > void __attribute__((interrupt_loc(VEC_RTC))) > #else > void __attribute__((interrupt_loc(0xFF00))) > #endif > isr_rtc (void) > { > clock_var++; > } > From 5ed0fbad2b15c1a0419c4046fc11488811c68152 Mon Sep 17 00:00:00 2001 > From: Jozef Lawrynowicz > Date: Tue, 20 Oct 2020 10:44:37 +0100 > Subject: [PATCH] Implement SHF_GNU_ABIND > > --- > bfd/elf-bfd.h | 10 +- > bfd/elf.c | 9 +- > bfd/elflink.c | 133 ++++- > binutils/readelf.c | 10 + > gas/config/obj-elf.c | 47 +- > gas/config/obj-elf.h | 1 + > gas/testsuite/gas/elf/section10.d | 4 +- > gas/testsuite/gas/elf/section10.s | 4 +- > include/elf/common.h | 2 + > include/elf/external.h | 14 + > ld/configure.tgt | 1 - > ld/ldelfgen.c | 568 ++++++++++++++++++++++ > ld/ldlang.c | 8 +- > ld/ldlang.h | 5 + > ld/testsuite/ld-arm/abind-1.d | 49 ++ > ld/testsuite/ld-arm/abind-1.s | 183 +++++++ > ld/testsuite/ld-arm/arm-elf.exp | 2 + > ld/testsuite/ld-elf/abind-1.s | 57 +++ > ld/testsuite/ld-elf/abind-1a.d | 27 + > ld/testsuite/ld-elf/abind-1a.ld | 28 ++ > ld/testsuite/ld-elf/abind-1b.d | 27 + > ld/testsuite/ld-elf/abind-1b.ld | 28 ++ > ld/testsuite/ld-elf/abind-1c.d | 27 + > ld/testsuite/ld-elf/abind-1c.ld | 28 ++ > ld/testsuite/ld-elf/abind-1d.d | 27 + > ld/testsuite/ld-elf/abind-1d.ld | 28 ++ > ld/testsuite/ld-elf/abind-1e.d | 27 + > ld/testsuite/ld-elf/abind-1e.ld | 27 + > ld/testsuite/ld-elf/abind-1f.d | 27 + > ld/testsuite/ld-elf/abind-1f.ld | 28 ++ > ld/testsuite/ld-elf/abind-1g.d | 27 + > ld/testsuite/ld-elf/abind-1g.ld | 27 + > ld/testsuite/ld-elf/abind-1h.d | 27 + > ld/testsuite/ld-elf/abind-1h.ld | 27 + > ld/testsuite/ld-elf/abind-1i.d | 27 + > ld/testsuite/ld-elf/abind-1i.ld | 22 + > ld/testsuite/ld-elf/abind-2.s | 183 +++++++ > ld/testsuite/ld-elf/abind-2a.d | 73 +++ > ld/testsuite/ld-elf/abind-2a.ld | 28 ++ > ld/testsuite/ld-elf/abind-2b.d | 73 +++ > ld/testsuite/ld-elf/abind-2b.ld | 28 ++ > ld/testsuite/ld-elf/abind-2c.d | 73 +++ > ld/testsuite/ld-elf/abind-2c.ld | 27 + > ld/testsuite/ld-elf/abind-2d.d | 73 +++ > ld/testsuite/ld-elf/abind-2d.ld | 28 ++ > ld/testsuite/ld-elf/abind-2e.d | 73 +++ > ld/testsuite/ld-elf/abind-2e.ld | 27 + > ld/testsuite/ld-elf/abind-2f.d | 73 +++ > ld/testsuite/ld-elf/abind-2f.ld | 27 + > ld/testsuite/ld-elf/abind-2g.d | 73 +++ > ld/testsuite/ld-elf/abind-2g.ld | 22 + > ld/testsuite/ld-msp430-elf/location-1.d | 23 + > ld/testsuite/ld-msp430-elf/location-1.s | 98 ++++ > ld/testsuite/ld-msp430-elf/location-2.d | 30 ++ > ld/testsuite/ld-msp430-elf/location-2.s | 76 +++ > ld/testsuite/ld-msp430-elf/location-3.d | 10 + > ld/testsuite/ld-msp430-elf/location-3.s | 12 + > ld/testsuite/ld-msp430-elf/msp430-elf.exp | 4 + > ld/testsuite/ld-x86-64/abind-1.d | 54 ++ > ld/testsuite/ld-x86-64/abind-1.s | 175 +++++++ > ld/testsuite/ld-x86-64/x86-64.exp | 1 + > 61 files changed, 2938 insertions(+), 19 deletions(-) > create mode 100644 ld/testsuite/ld-arm/abind-1.d > create mode 100644 ld/testsuite/ld-arm/abind-1.s > create mode 100644 ld/testsuite/ld-elf/abind-1.s > create mode 100644 ld/testsuite/ld-elf/abind-1a.d > create mode 100644 ld/testsuite/ld-elf/abind-1a.ld > create mode 100644 ld/testsuite/ld-elf/abind-1b.d > create mode 100644 ld/testsuite/ld-elf/abind-1b.ld > create mode 100644 ld/testsuite/ld-elf/abind-1c.d > create mode 100644 ld/testsuite/ld-elf/abind-1c.ld > create mode 100644 ld/testsuite/ld-elf/abind-1d.d > create mode 100644 ld/testsuite/ld-elf/abind-1d.ld > create mode 100644 ld/testsuite/ld-elf/abind-1e.d > create mode 100644 ld/testsuite/ld-elf/abind-1e.ld > create mode 100644 ld/testsuite/ld-elf/abind-1f.d > create mode 100644 ld/testsuite/ld-elf/abind-1f.ld > create mode 100644 ld/testsuite/ld-elf/abind-1g.d > create mode 100644 ld/testsuite/ld-elf/abind-1g.ld > create mode 100644 ld/testsuite/ld-elf/abind-1h.d > create mode 100644 ld/testsuite/ld-elf/abind-1h.ld > create mode 100644 ld/testsuite/ld-elf/abind-1i.d > create mode 100644 ld/testsuite/ld-elf/abind-1i.ld > create mode 100644 ld/testsuite/ld-elf/abind-2.s > create mode 100644 ld/testsuite/ld-elf/abind-2a.d > create mode 100644 ld/testsuite/ld-elf/abind-2a.ld > create mode 100644 ld/testsuite/ld-elf/abind-2b.d > create mode 100644 ld/testsuite/ld-elf/abind-2b.ld > create mode 100644 ld/testsuite/ld-elf/abind-2c.d > create mode 100644 ld/testsuite/ld-elf/abind-2c.ld > create mode 100644 ld/testsuite/ld-elf/abind-2d.d > create mode 100644 ld/testsuite/ld-elf/abind-2d.ld > create mode 100644 ld/testsuite/ld-elf/abind-2e.d > create mode 100644 ld/testsuite/ld-elf/abind-2e.ld > create mode 100644 ld/testsuite/ld-elf/abind-2f.d > create mode 100644 ld/testsuite/ld-elf/abind-2f.ld > create mode 100644 ld/testsuite/ld-elf/abind-2g.d > create mode 100644 ld/testsuite/ld-elf/abind-2g.ld > create mode 100644 ld/testsuite/ld-msp430-elf/location-1.d > create mode 100644 ld/testsuite/ld-msp430-elf/location-1.s > create mode 100644 ld/testsuite/ld-msp430-elf/location-2.d > create mode 100644 ld/testsuite/ld-msp430-elf/location-2.s > create mode 100644 ld/testsuite/ld-msp430-elf/location-3.d > create mode 100644 ld/testsuite/ld-msp430-elf/location-3.s > create mode 100644 ld/testsuite/ld-x86-64/abind-1.d > create mode 100644 ld/testsuite/ld-x86-64/abind-1.s > > diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h > index ffb75f7919..1dc08ba2ba 100644 > --- a/bfd/elf-bfd.h > +++ b/bfd/elf-bfd.h > @@ -1897,15 +1897,17 @@ struct output_elf_obj_tdata > bfd_boolean flags_init; > }; > > -/* Indicate if the bfd contains SHF_GNU_MBIND/SHF_GNU_RETAIN sections or > - symbols that have the STT_GNU_IFUNC symbol type or STB_GNU_UNIQUE > - binding. Used to set the osabi field in the ELF header structure. */ > +/* Indicate if the bfd contains SHF_GNU_MBIND, SHF_GNU_RETAIN or SHF_GNU_ABIND > + sections or symbols that have the STT_GNU_IFUNC symbol type or > + STB_GNU_UNIQUE binding. Used to set the osabi field in the ELF header > + structure. */ > enum elf_gnu_osabi > { > elf_gnu_osabi_mbind = 1 << 0, > elf_gnu_osabi_ifunc = 1 << 1, > elf_gnu_osabi_unique = 1 << 2, > elf_gnu_osabi_retain = 1 << 3, > + elf_gnu_osabi_abind = 1 << 4, > }; > > typedef struct elf_section_list > @@ -2035,7 +2037,7 @@ struct elf_obj_tdata > ENUM_BITFIELD (dynamic_lib_link_class) dyn_lib_class : 4; > > /* Whether the bfd uses OS specific bits that require ELFOSABI_GNU. */ > - ENUM_BITFIELD (elf_gnu_osabi) has_gnu_osabi : 4; > + ENUM_BITFIELD (elf_gnu_osabi) has_gnu_osabi : 5; > > /* Whether if the bfd contains the GNU_PROPERTY_NO_COPY_ON_PROTECTED > property. */ > diff --git a/bfd/elf.c b/bfd/elf.c > index dc097e825a..5e30b1016a 100644 > --- a/bfd/elf.c > +++ b/bfd/elf.c > @@ -3284,8 +3284,13 @@ elf_fake_sections (bfd *abfd, asection *asect, void *fsarg) > > /* Don't clear sh_flags. Assembler may set additional bits. */ > > - if ((asect->flags & SEC_ALLOC) != 0 > - || asect->user_set_vma) > + if (!arg->link_info > + && elf_section_flags (asect) & SHF_GNU_ABIND) > + { > + /* Don't clobber sh_addr already set for a GNU_ABIND section. */ > + } > + else if ((asect->flags & SEC_ALLOC) != 0 > + || asect->user_set_vma) > this_hdr->sh_addr = asect->vma * bfd_octets_per_byte (abfd, asect); > else > this_hdr->sh_addr = 0; > diff --git a/bfd/elflink.c b/bfd/elflink.c > index 742254055c..d93e744cf1 100644 > --- a/bfd/elflink.c > +++ b/bfd/elflink.c > @@ -4044,6 +4044,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) > size_t tabsize = 0; > asection *s; > bfd_boolean just_syms; > + static bfd_boolean created_abind_init_sec = FALSE; > > htab = elf_hash_table (info); > bed = get_elf_backend_data (abfd); > @@ -4081,16 +4082,16 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) > (_("alternate ELF machine code found (%d) in %pB, expecting %d"), > ehdr->e_machine, abfd, bed->elf_machine_code); > > - /* As a GNU extension, any input sections which are named > - .gnu.warning.SYMBOL are treated as warning symbols for the given > - symbol. This differs from .gnu.warning sections, which generate > - warnings when they are included in an output file. */ > - /* PR 12761: Also generate this warning when building shared libraries. */ > for (s = abfd->sections; s != NULL; s = s->next) > { > const char *name; > > name = bfd_section_name (s); > + /* As a GNU extension, any input sections which are named > + .gnu.warning.SYMBOL are treated as warning symbols for the given > + symbol. This differs from .gnu.warning sections, which generate > + warnings when they are included in an output file. */ > + /* PR 12761: Also generate this warning when building shared libraries. */ > if (CONST_STRNEQ (name, ".gnu.warning.")) > { > char *msg; > @@ -4146,6 +4147,65 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) > s->flags |= SEC_EXCLUDE; > } > } > + else if (!bfd_link_relocatable (info) > + && (elf_section_data (s)->this_hdr.sh_flags & SHF_GNU_ABIND)) > + { > + /* Orphan sections with the SHF_GNU_ABIND flag so they can be freely > + moved around the statement list, by renaming them so they don't > + match a linker script rule. */ > + bfd_rename_section (s, concat (".gnu.abind", s->name, (const char *)NULL)); > + > + if (!created_abind_init_sec) > + { > + /* Create .gnu.abind_init_array and an undefined symbol for the > + library function required to make use of it. */ > + asection *s_init; > + flagword flags = (SEC_HAS_CONTENTS | SEC_READONLY > + | SEC_ALLOC | SEC_LOAD | SEC_KEEP); > + > + s_init = bfd_make_section_anyway_with_flags (abfd, ".gnu.abind_init_array", flags); > + if (s_init == NULL) > + { > + _bfd_error_handler > + (_("%pB: could not create .gnu.abind_init_array section\n"), abfd); > + goto error_return; > + } > + > + if (bed->s->arch_size == 64) > + { > + elf_section_data (s_init)->this_hdr.sh_entsize > + = sizeof (Elf64_External_AbindInitArray_Entry); > + bfd_set_section_alignment (s_init, 8); > + } > + else > + { > + elf_section_data (s_init)->this_hdr.sh_entsize > + = sizeof (Elf32_External_AbindInitArray_Entry); > + bfd_set_section_alignment (s_init, 4); > + } > + > + /* Create an undefined symbol to ............. */ > + struct bfd_link_hash_entry *h; > + > + h = bfd_link_hash_lookup (info->hash, "__run_gnu_abind_init_array", TRUE, FALSE, TRUE); > + if (h == NULL) > + { > + _bfd_error_handler > + (_("%pB: could not create __run_gnu_abind_init_array symbol\n"), abfd); > + goto error_return; > + } > + if (h->type == bfd_link_hash_new) > + { > + h->type = bfd_link_hash_undefined; > + h->u.undef.abfd = NULL; > + h->non_ir_ref_regular = TRUE; > + if (is_elf_hash_table (info->hash)) > + ((struct elf_link_hash_entry *) h)->mark = 1; > + bfd_link_add_undef (info->hash, h); > + } > + created_abind_init_sec = TRUE; > + } > + } > } > > just_syms = ((s = abfd->sections) != NULL > @@ -9801,6 +9861,66 @@ elf_link_output_symstrtab (struct elf_final_link_info *flinfo, > return 1; > } > > +static bfd_boolean > +_elf_link_swap_out_abind_init_array (bfd *abfd) > +{ > + asection *init_sec, *s; > + bfd_vma pos; > + const struct elf_backend_data *bed; > + int sizeof_addr; > + > + init_sec = bfd_get_section_by_name (abfd, ".gnu.abind_init_array"); > + if (init_sec == NULL) > + return TRUE; > + > + bed = get_elf_backend_data (abfd); > + > + if (bed->s->arch_size == 64) > + { > + elf_section_data (init_sec)->this_hdr.sh_entsize > + = sizeof (Elf64_External_AbindInitArray_Entry); > + sizeof_addr = 8; > + } > + else > + { > + elf_section_data (init_sec)->this_hdr.sh_entsize > + = sizeof (Elf32_External_AbindInitArray_Entry); > + sizeof_addr = 4; > + } > + > + bfd_byte *data_contents = bfd_malloc (init_sec->size); > + memset (data_contents, 0, init_sec->size); > + pos = 0; > + > + for (s = abfd->sections; s != NULL; s = s->next) > + { > + if ((elf_section_flags (s) & SHF_GNU_ABIND) == 0 > + /* .bss sections and those with LMA != VMA will require runtime > + initialization using .gnu.abind_init_array. */ > + || !(s->lma != s->vma > + || (s->flags & (SEC_DATA | SEC_LOAD | SEC_READONLY | SEC_CODE)) == 0)) > + continue; > + > + if (pos >= init_sec->size) > + { > + _bfd_error_handler(_("%pB: .gnu.abind_init_array has incorrect size\n"), abfd); > + return FALSE; > + } > + > + /* FIXME Use a "swap_out" function to write out the entry. */ > + /* When LMA == VMA, __run_gnu_abind_init_array knows the section is for > + .bss and will instead zero-initialize for the given size. */ > + memcpy (data_contents + pos, &s->vma, sizeof_addr); > + pos += sizeof_addr; > + memcpy (data_contents + pos, &s->lma, sizeof_addr); > + pos += sizeof_addr; > + memcpy (data_contents + pos, &s->size, sizeof_addr); > + pos += sizeof_addr; > + } > + bfd_set_section_contents (abfd, init_sec, data_contents, 0, init_sec->size); > + return TRUE; > +} > + > /* Swap symbols out to the symbol table and flush the output symbols to > the file. */ > > @@ -12823,6 +12943,9 @@ bfd_elf_final_link (bfd *abfd, struct bfd_link_info *info) > goto return_local_hash_table; > } > > + /* Swap out .gnu.abind_init_array. */ > + _elf_link_swap_out_abind_init_array (abfd); > + > /* Now we know the size of the symtab section. */ > if (bfd_get_symcount (abfd) > 0) > { > diff --git a/binutils/readelf.c b/binutils/readelf.c > index e6ec99a2cc..f43687c1ed 100644 > --- a/binutils/readelf.c > +++ b/binutils/readelf.c > @@ -5979,6 +5979,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) > /* 25 */ { STRING_COMMA_LEN ("VLE") }, > /* GNU specific. */ > /* 26 */ { STRING_COMMA_LEN ("GNU_RETAIN") }, > + /* GNU specific. */ > + /* 27 */ { STRING_COMMA_LEN ("GNU_ABIND") }, > }; > > if (do_section_details) > @@ -6070,6 +6072,8 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) > case ELFOSABI_FREEBSD: > if (flag == SHF_GNU_RETAIN) > sindex = 26; > + else if (flag == SHF_GNU_ABIND) > + sindex = 27; > /* Fall through */ > case ELFOSABI_NONE: > if (flag == SHF_GNU_MBIND) > @@ -6148,6 +6152,12 @@ get_elf_section_flags (Filedata * filedata, bfd_vma sh_flags) > *p = 'R'; > break; > } > + else if (flag == SHF_GNU_ABIND) > + { > + *p = 'a'; > + break; > + } > + > /* Fall through */ > case ELFOSABI_NONE: > if (flag == SHF_GNU_MBIND) > diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c > index 6586478975..2597b1018a 100644 > --- a/gas/config/obj-elf.c > +++ b/gas/config/obj-elf.c > @@ -741,6 +741,7 @@ obj_elf_change_section (const char *name, > elf_section_type (sec) = type; > elf_section_flags (sec) = attr; > elf_section_data (sec)->this_hdr.sh_info = match_p->sh_info; > + elf_section_data (sec)->this_hdr.sh_addr = match_p->sh_addr; > > /* Prevent SEC_HAS_CONTENTS from being inadvertently set. */ > if (type == SHT_NOBITS) > @@ -801,7 +802,14 @@ obj_elf_change_section (const char *name, > | SEC_THREAD_LOCAL)) > || ((elf_tdata (stdoutput)->has_gnu_osabi & elf_gnu_osabi_retain) > && ((elf_section_flags (old_sec) ^ match_p->sh_flags) > - & SHF_GNU_RETAIN))) > + & SHF_GNU_RETAIN)) > + /* Check GNU_ABIND state matches, and the address are the > + same. */ > + || ((elf_tdata (stdoutput)->has_gnu_osabi & elf_gnu_osabi_abind) > + && (((elf_section_flags (old_sec) ^ match_p->sh_flags) > + & SHF_GNU_ABIND) > + || ((elf_section_data (old_sec)->this_hdr.sh_addr > + != match_p->sh_addr))))) > { > if (ssect != NULL) > as_warn (_("ignoring changed section attributes for %s"), name); > @@ -867,6 +875,9 @@ obj_elf_parse_section_letters (char *str, size_t len, > case 'R': > *gnu_attr |= SHF_GNU_RETAIN; > break; > + case 'A': > + *gnu_attr |= SHF_GNU_ABIND; > + break; > case '?': > *is_clone = TRUE; > break; > @@ -1332,6 +1343,36 @@ obj_elf_section (int push) > if ((gnu_attr & SHF_GNU_RETAIN) != 0) > match.sh_flags |= SHF_GNU_RETAIN; > > + if ((gnu_attr & SHF_GNU_ABIND) != 0 && *input_line_pointer == ',') > + { > + char *save = input_line_pointer; > + ++input_line_pointer; > + SKIP_WHITESPACE (); > + if (ISDIGIT (* input_line_pointer)) > + { > + char *t = input_line_pointer; > + match.sh_addr = strtoul (input_line_pointer, > + &input_line_pointer, 0); > + if (match.sh_addr == (unsigned int) -1) > + { > + as_warn (_("invalid address for GNU_ABIND section: %s"), t); > + match.sh_addr = 0; > + } > + } > + else > + { > + as_warn (_("expected integer constant for GNU_ABIND section address")); > + match.sh_addr = 0; > + input_line_pointer = save; > + } > + } > + else if ((attr & SHF_GNU_ABIND) != 0) > + { > + as_warn (_("address for SHF_GNU_ABIND not specified")); > + attr &= ~SHF_GNU_ABIND; > + } > + > + > if (*input_line_pointer == ',') > { > char *save = input_line_pointer; > @@ -1420,7 +1461,7 @@ obj_elf_section (int push) > done: > demand_empty_rest_of_line (); > > - if ((gnu_attr & (SHF_GNU_MBIND | SHF_GNU_RETAIN)) != 0) > + if ((gnu_attr & SHF_MASKOS) != 0) > { > struct elf_backend_data *bed; > bfd_boolean mbind_p = (gnu_attr & SHF_GNU_MBIND) != 0; > @@ -1446,6 +1487,8 @@ obj_elf_section (int push) > elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_mbind; > if ((gnu_attr & SHF_GNU_RETAIN) != 0) > elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_retain; > + if ((gnu_attr & SHF_GNU_ABIND) != 0) > + elf_tdata (stdoutput)->has_gnu_osabi |= elf_gnu_osabi_abind; > > attr |= gnu_attr; > } > diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h > index 0a91ed462f..c5492cc8bc 100644 > --- a/gas/config/obj-elf.h > +++ b/gas/config/obj-elf.h > @@ -108,6 +108,7 @@ struct elf_section_match > const char * linked_to_symbol_name; > unsigned int section_id; > unsigned int sh_info; /* ELF section information. */ > + bfd_vma sh_addr; /* ELF section address. */ > bfd_vma sh_flags; /* ELF section flags. */ > flagword flags; > }; > diff --git a/gas/testsuite/gas/elf/section10.d b/gas/testsuite/gas/elf/section10.d > index 6aa7b088b1..8346d7b13c 100644 > --- a/gas/testsuite/gas/elf/section10.d > +++ b/gas/testsuite/gas/elf/section10.d > @@ -18,7 +18,7 @@ > #... > [ ]*\[.*\][ ]+sec3 > [ ]*PROGBITS.* > -[ ]*\[.*fedff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\) > +[ ]*\[.*fe9ff030\]: MERGE, STRINGS,.* EXCLUDE, OS \(.*e900000\), PROC \(.*[3467]0000000\), UNKNOWN \(0+0ff000\) > #... > [ ]*\[.*\][ ]+sec4 > [ ]*LOOS\+0x11[ ].* > @@ -26,7 +26,7 @@ > #... > [ ]*\[.*\][ ]+sec5 > [ ]*LOUSER\+0x9[ ].* > -[ ]*\[.*fedf0000\]:.* EXCLUDE, OS \(.*ed00000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) > +[ ]*\[.*fe9f0000\]:.* EXCLUDE, OS \(.*e900000\), PROC \(.*[3467]0000000\), UNKNOWN \(.*f0000\) > [ ]*\[.*\][ ]+.data.foo > [ ]*LOUSER\+0x7f000000[ ].* > [ ]*\[0+003\]: WRITE, ALLOC > diff --git a/gas/testsuite/gas/elf/section10.s b/gas/testsuite/gas/elf/section10.s > index d52b3458fb..1236045c3c 100644 > --- a/gas/testsuite/gas/elf/section10.s > +++ b/gas/testsuite/gas/elf/section10.s > @@ -7,7 +7,7 @@ > .word 2 > > # Make sure that specifying further arguments to .sections is still supported > - .section sec3, "0xfedff000MS", %progbits, 32 > + .section sec3, "0xfe9ff000MS", %progbits, 32 > .word 3 > > # Make sure that extra flags can be set for well known sections as well. > @@ -19,7 +19,7 @@ > .word 5 > > # Test both together, with a quoted type value. > - .section sec5, "0xfedf0000", "0x80000009" > + .section sec5, "0xfe9f0000", "0x80000009" > .word 6 > > # Test that declaring an extended version of a known special section works. > diff --git a/include/elf/common.h b/include/elf/common.h > index c01e562c78..babff115d9 100644 > --- a/include/elf/common.h > +++ b/include/elf/common.h > @@ -555,6 +555,8 @@ > #define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */ > #define SHF_GNU_BUILD_NOTE (1 << 20) /* Section contains GNU BUILD ATTRIBUTE notes. */ > #define SHF_GNU_RETAIN (1 << 21) /* Section should not be garbage collected by the linker. */ > +#define SHF_GNU_ABIND (1 << 22) /* Section should placed at a specific VMA. */ > + > #define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */ > > /* This used to be implemented as a processor specific section flag. > diff --git a/include/elf/external.h b/include/elf/external.h > index 230fdabd87..6f6e678dcd 100644 > --- a/include/elf/external.h > +++ b/include/elf/external.h > @@ -311,6 +311,20 @@ typedef struct > unsigned char a_val[8]; > } Elf64_External_Auxv; > > +typedef struct > +{ > + unsigned char vma[4]; > + unsigned char lma[4]; > + unsigned char size[4]; > +} Elf32_External_AbindInitArray_Entry; > + > +typedef struct > +{ > + unsigned char vma[8]; > + unsigned char lma[8]; > + unsigned char size[8]; > +} Elf64_External_AbindInitArray_Entry; > + > /* Size of SHT_GROUP section entry. */ > > #define GRP_ENTRY_SIZE 4 > diff --git a/ld/configure.tgt b/ld/configure.tgt > index 70359301b5..9db64ed12d 100644 > --- a/ld/configure.tgt > +++ b/ld/configure.tgt > @@ -584,7 +584,6 @@ moxie-*-*) targ_emul=elf32moxie > ;; > msp430-*-*) targ_emul=msp430elf > targ_extra_emuls="msp430X" > - targ_extra_ofiles=ldelfgen.o > ;; > mt-*elf) targ_emul=elf32mt > targ_extra_ofiles=ldelfgen.o > diff --git a/ld/ldelfgen.c b/ld/ldelfgen.c > index 3a5619435c..c1b9f8c1ab 100644 > --- a/ld/ldelfgen.c > +++ b/ld/ldelfgen.c > @@ -30,11 +30,18 @@ > #include "elf-bfd.h" > #include "ldelfgen.h" > > +static bfd_boolean place_bound_sections (void); > +static void dump_sections (lang_statement_list_type *root, lang_memory_region_type *r, int indent); > + > + > void > ldelf_map_segments (bfd_boolean need_layout) > { > int tries = 10; > > + if (!bfd_link_relocatable (&link_info)) > + place_bound_sections (); > + > do > { > lang_relax_sections (need_layout); > @@ -211,3 +218,564 @@ extern void ldelf_examine_strtab_for_ctf > struct elf_strtab_hash *symstrtab ATTRIBUTE_UNUSED) > {} > #endif > + > + > +/* Start SHF_GNU_ABIND handling. */ > + > +/* Insert __gnu_abind_init_array_{start,end} symbols at the start/end of > + .gnu.abind_init_array. */ > +static bfd_boolean > +insert_abind_init_array_symbols (void) > +{ > + lang_statement_union_type * curr; > + > + lang_relax_sections (TRUE); > + > + for (curr = stat_ptr->head; curr != NULL; curr = curr->header.next) > + { > + switch (curr->header.type) > + { > + case lang_output_section_statement_enum: > + if (curr->output_section_statement.bfd_section > + && strcmp (curr->output_section_statement.bfd_section->name, > + ".gnu.abind_init_array") == 0) > + { > + asection *os = curr->output_section_statement.bfd_section; > + /* FIXME this gets orphaned at the end of the map file would be > + good to attach it for aesthetics. */ > + lang_add_assignment (exp_provide ("__gnu_abind_init_array_start", > + exp_intop (os->vma), FALSE)); > + lang_add_assignment (exp_provide ("__gnu_abind_init_array_end", > + exp_intop (os->vma + os->size), > + FALSE)); > + return TRUE; > + } > + break; > + default: > + break; > + } > + } > + return FALSE; > +} > + > +/* Check a memory region exists at the address specified for the GNU_ABIND > + section, and that we can place the section in that region. */ > +static lang_memory_region_type * > +get_region_for_abind (asection *sec, > + bfd_boolean validate_flags ATTRIBUTE_UNUSED) > +{ > + bfd_vma addr = sec->vma; > + lang_memory_region_type *r; > + lang_memory_region_type *ret = NULL; > + > + for (r = get_memory_region_list (); r != NULL; r = r->next) > + { > + /* The default memory region spans the entire address space. Use it if > + no other memory region contains the address. */ > + if (strcmp ("*default*", r->name_list.name) == 0) > + ret = r; > + else if (addr >= r->origin && addr < (r->origin + r->length)) > + { > + /* FIXME/TODO Check the region we want to place the section in is > + compatible with its type. */ > +#if 0 > + if (validate_flags > + && (!verify_region_compatibility (r, stat_ptr, sec->flags))) > + { > + einfo (_("%P: warning: GNU_ABIND section '%s' is not compatible " > + "with the memory region '%s' containing address 0x%v\n"), > + sec->name, r->name_list.name, addr); > + return NULL; > + } > +#endif > + return r; > + } > + } > + return ret; > +} > + > + > +/* Detach the output section S from the list that starts from ROOT. */ > +static bfd_boolean > +detach_output_sec (asection *s, lang_statement_list_type *root, > + bfd_boolean dump) > +{ > + asection *os; > + lang_statement_union_type * prev = NULL; > + lang_statement_union_type * curr; > + lang_output_section_statement_type * os_stat; > + > + for (curr = root->head; curr != NULL; curr = curr->header.next) > + { > + switch (curr->header.type) > + { > + case lang_output_section_statement_enum: > + os_stat = &curr->output_section_statement; > + if (!os_stat->bfd_section) > + break; > + > + os = os_stat->bfd_section; > + > + if (os == s) > + { > + /* If this is the last statement, and we are detaching this > + statement, we have to point the list tail to the previous > + elements' next pointer. */ > + if (curr->header.next == NULL) > + root->tail = &prev->header.next; > + > + /* Adjust the next statement pointed to by the previous element. */ > + if (prev == NULL) > + root->head = curr->header.next; > + else > + prev->header.next = curr->header.next; > + > + /* This statement is no longer part of any list, so clear the next > + element it points to. */ > + curr->header.next = NULL; > + > + lang_relax_sections (TRUE); > + return TRUE; > + } > + break; > + > + case lang_group_statement_enum: > + if (detach_output_sec (s, &curr->group_statement.children, dump)) > + return TRUE; > + break; > + > + default: > + break; > + } > + prev = curr; > + } > + return FALSE; > +} > + > +static int > +compare_abind_sec_vma (const void *a, const void *b) > +{ > + asection *asec = *(asection **) a, *bsec = *(asection **) b; > + > + if (asec->vma > bsec->vma) > + return 1; > + else if (asec->vma < bsec->vma) > + return -1; > + > + return 0; > +} > + > +/* Create a list of GNU_ABIND sections, sorted in ascending order of > + their desired VMA. */ > +static unsigned int > +sort_abind_secs (asection ***sec_list_p) > +{ > + bfd *ibfd; > + asection *sec; > + asection **sec_list; > + unsigned int sec_count = 0; > + unsigned int list_size = 10; > + > + sec_list = (asection **) xmalloc (list_size * sizeof (asection *)); > + *sec_list_p = sec_list; > + > + for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link.next) > + for (sec = ibfd->sections; sec != NULL; sec = sec->next) > + { > + if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour > + || !(elf_section_flags (sec) & SHF_GNU_ABIND) > + || (elf_section_flags (sec) & SEC_EXCLUDE) > + || strcmp (sec->output_section->name, DISCARD_SECTION_NAME) == 0 > + || sec->output_section == bfd_abs_section_ptr > + || (link_info.gc_sections && !sec->gc_mark)) > + continue; > + > + /* FIXME add an option to disable placement of lma != vma bound sections. */ > + /*if (sec->output_section->lma != sec->output_section->vma)*/ > + /*continue;*/ > + > + /* Before we go any further, validate the address of section. > + We may not be able to place it there at all. */ > + /*if (get_region_for_abind (sec, TRUE) == NULL)*/ > + /*continue;*/ > + > + if (sec_count == list_size) > + { > + list_size *= 2; > + sec_list = (asection **) > + xrealloc (sec_list, list_size * sizeof (asection *)); > + } > + > + sec_list[sec_count++] = sec; > + > + /* Sort the SHF_GNU_ABIND input sections by their specified VMA. */ > + qsort (sec_list, sec_count, sizeof (asection *), &compare_abind_sec_vma); > + } > + return sec_count; > +} > + > +/* Initialize a new lang_statement_union_type with the given output section > + statement. */ > +static lang_statement_union_type * > +insert_os_stat (lang_output_section_statement_type *os_stat) > +{ > + lang_statement_union_type *new_stmt; > + new_stmt = stat_alloc (sizeof (lang_output_section_statement_type)); > + new_stmt->header.type = lang_output_section_statement_enum; > + > + new_stmt->output_section_statement = *os_stat; > + new_stmt->output_section_statement.addr_tree = NULL; > + new_stmt->header.next = NULL; > + return new_stmt; > +} > + > +/* Initialize an output section with a wild statement. */ > +static void > +insert_wild (lang_statement_list_type *list) > +{ > + lang_wild_statement_type *wild = NULL; > + > + wild = stat_alloc (sizeof (lang_wild_statement_type)); > + wild->header.next = NULL; > + wild->header.type = lang_wild_statement_enum; > + > + wild->filename = NULL; > + wild->filenames_sorted = FALSE; > + wild->section_flag_list = NULL; > + wild->exclude_name_list = NULL; > + wild->section_list = NULL; > + wild->keep_sections = FALSE; > + lang_list_init (&wild->children); > + > + *(list->tail) = (void *)wild; > + list->tail = &wild->header.next; > + > + lang_relax_sections (TRUE); > +} > + > +/* Return TRUE if this is the last output section statement in the entire statement list. */ > +static bfd_boolean > +is_last_real_os (lang_statement_union_type *os_stat) > +{ > + lang_statement_union_type *curr; > + for (curr = os_stat->header.next; curr != NULL; curr = curr->header.next) > + { > + switch (curr->header.type) > + { > + case lang_output_section_statement_enum: > + if (curr->output_section_statement.bfd_section > + && (curr->output_section_statement.bfd_section->flags & SEC_ALLOC)) > + return FALSE; > + break; > + default: > + /* FIXME: Do we need to handle group statements? */ > + break; > + } > + } > + return TRUE; > +} > + > + > +/* Place SEC before the output section os_stat. If os_stat is NULL, there > + should be free space at the desired address and we attach it to the > + statement list as required. */ > +static lang_output_section_statement_type * > +move_abind_os (asection *sec, lang_statement_list_type *root) > +{ > + lang_statement_union_type * curr; > + lang_statement_union_type * prev = NULL; > + lang_statement_union_type * prev_os_stat = NULL; > + lang_statement_union_type * insert_after = NULL; > + bfd_vma addr = sec->vma; > + lang_output_section_statement_type * os_stat; > + asection *os; > + const int dump = 0; > + if (dump) > + printf ("\nMoving %s\n", sec->name); > + > + /* We detached the output section statements for all GNU_ABIND sections > + earlier. Find the statement for this output section, and reattach it. */ > + os_stat = lang_output_section_find (sec->output_section->name); > + os_stat->region = get_region_for_abind (sec, FALSE); > + > + /* Find the position in the statement list to insert this GNU_ABIND > + section. */ > + for (curr = root->head; curr != NULL; curr = curr->header.next) > + { > + switch (curr->header.type) > + { > + case lang_output_section_statement_enum: > + if (curr->output_section_statement.bfd_section == NULL > + || bfd_is_abs_section (curr->output_section_statement.bfd_section)) > + { > + /* Always keep a record of the last output section statement, so a > + GNU_ABIND section can be attached after it. */ > + prev_os_stat = prev = curr; > + continue; > + } > + > + os = curr->output_section_statement.bfd_section; > + if (dump) > + printf (" %s vma 0x%lx size 0x%lx\n", os->name, > + os->vma, os->size); > + > + if (os->vma >= addr || (os->vma + os->size > addr)) > + { > + /* Between the end of the prev_os_stat and the end of this current > + output section is the desired VMA for the GNU_ABIND section. > + Insert the GNU_ABIND section after prev_os_stat. > + If there is no prev_os_stat insert at the first suitable place in the overall > + statement list, using insert_os_after to find that place. */ > + if (prev_os_stat == NULL) > + insert_after = *(insert_os_after ((lang_output_section_statement_type *)root->head)); > + else > + insert_after = prev_os_stat; > + } > + else if (curr->header.next == NULL || is_last_real_os (curr)) > + { > + /* Insert at the end of the statement list/after the last output > + section. */ > + insert_after = curr; > + } > + > + if (insert_after != NULL) > + { > + lang_statement_union_type *new_stmt = insert_os_stat (os_stat); > + new_stmt->output_section_statement.addr_tree = exp_intop (addr); > + > + if (dump) > + { > + if (insert_after->header.type == lang_output_section_statement_enum > + && insert_after->output_section_statement.bfd_section) > + printf (" INSERT %s HERE, after %s\n", sec->name, > + insert_after->output_section_statement.bfd_section->name); > + else > + printf (" INSERT %s HERE, after unknown\n", sec->name); > + } > + > + new_stmt->header.next = insert_after->header.next; > + insert_after->header.next = new_stmt; > + > + if (insert_after->header.next == NULL) > + root->tail = &new_stmt->header.next; > + > + return &new_stmt->output_section_statement; > + } > + prev_os_stat = curr; > + break; > + default: > + if (dump) > + printf (" statement type %d\n", curr->header.type); > + break; > + } > + prev = curr; > + } > + return NULL; > +} > + > +/* Place SHF_GNU_ABIND sections at their requested VMAs, if possible. */ > +static bfd_boolean > +place_bound_sections (void) > +{ > + bfd *ibfd; > + asection *sec; > + unsigned int num_abind; > + lang_output_section_statement_type *os_stat; > + unsigned int i; > + asection **abind_secs; > + > + num_abind = sort_abind_secs (&abind_secs); > + > + if (num_abind == 0) > + return TRUE; > + > + /* Detach the GNU_ABIND sections from the global statement list. This ensures that > + regular sections are in accurate positions each time we go to look at > + placing the GNU_ABIND section. > + Create .abind_*_init_array entries if required. */ > + for (i = 0; i < num_abind; i++) > + { > + static asection *init_sec = NULL; > + struct elf_link_hash_entry *h; > + > + sec = abind_secs[i]->output_section; > + > + /* .bss sections and those with LMA != VMA will require runtime > + initialization using .gnu.abind_init_array. */ > + if ((sec->lma != sec->vma > + || (sec->flags & (SEC_DATA | SEC_LOAD | SEC_READONLY | SEC_CODE)) == 0)) > + { > + if (init_sec == NULL) > + { > + asection *s; > + /* Find the input section version of .gnu.abind_init_array. > + Changes to the size of the output section don't persist. */ > + for (ibfd = link_info.input_bfds; ibfd != NULL; ibfd = ibfd->link.next) > + for (s = ibfd->sections; s != NULL; s = s->next) > + if (strcmp (s->name, ".gnu.abind_init_array") == 0) > + init_sec = s; > + > + /* .gnu.abind_init_array should have been created in > + elf_link_add_object_symbols. */ > + if (init_sec == NULL) > + { > + einfo (_("%X%P: .gnu.abind_init_array has not been created\n")); > + return FALSE; > + } > + } > + > + /* If the section will require a .gnu.abind_init_array entry, then additional > + support from the run time library is required. > + Verify that support is available by checking the > + __run_gnu_abind_init_array has been resolved. */ > + h = elf_link_hash_lookup (elf_hash_table (&link_info), > + "__run_gnu_abind_init_array", > + FALSE, FALSE, FALSE); > + > + if (h == NULL > + || (h != NULL && (h->root.type != bfd_link_hash_defined))) > + { > + /* If we could restore the .gnu.abind section to its original name > + and place it in its original output section, maybe this > + error wouldn't have to be fatal. However, if the program requires > + the section to be at a specific address, then it will not be > + correct if we can't place the ABIND section. */ > + einfo (_("%X%P: __run_gnu_abind_init_array symbol has not been resolved\n")); > + > + /* Report the remaining abind sections that can't be placed, then > + quit. */ > + for (; i < num_abind; i++) > + { > + if (!(sec->lma != sec->vma > + || (sec->flags & (SEC_DATA | SEC_LOAD | SEC_READONLY | SEC_CODE)) == 0)) > + continue; > + elf_section_flags (abind_secs[i]) &= ~SHF_GNU_ABIND; > + elf_section_flags (abind_secs[i]->output_section) &= ~SHF_GNU_ABIND; > + einfo (_("%X%P: SHF_GNU_ABIND section %s requires " > + "initialization from __run_gnu_abind_init_array\n"), abind_secs[i]->name); > + } > + return FALSE; > + } > + bfd_set_section_size (init_sec, init_sec->size > + + elf_section_data (init_sec)->this_hdr.sh_entsize); > + } > + > + if (!detach_output_sec (abind_secs[i]->output_section, stat_ptr, FALSE)) > + return FALSE; > + } > + > + > + for (i = 0; i < num_abind; i++) > + { > + lang_relax_sections (TRUE); > + sec = abind_secs[i]; > + os_stat = move_abind_os (sec, stat_ptr); > + > + if (os_stat == NULL) > + { > + einfo (_("%P: error: unable to place GNU_ABIND section %s\n"), sec->name); > + continue; > + } > + > + /* Refresh this bound section, which should only > + ever contain a SHF_GNU_ABIND input section. */ > + lang_list_init (&os_stat->children); > + insert_wild (&os_stat->children); > + /* We need to clear the output section before calling > + lang_add_section. */ > + sec->output_section = NULL; > + lang_add_section (&os_stat->children.head->wild_statement.children, > + sec, NULL, os_stat); > + } > + > + if (!insert_abind_init_array_symbols ()) > + { > + einfo (_("%P: couldn't find .gnu.abind_init_array section to define " > + "__gnu_abind_init_array_{start,end} symbols")); > + return FALSE; > + } > + return TRUE; > +} > + > +static void ATTRIBUTE_UNUSED > +dump_sections (lang_statement_list_type *root, lang_memory_region_type *r, int indent) > +{ > + lang_statement_union_type * curr; > + lang_output_section_statement_type * os_stat; > + asection *s; > + int i; > + > + for (curr = root->head; curr != NULL; curr = curr->header.next) > + { > + switch (curr->header.type) > + { > + case lang_input_section_enum: > + s = curr->input_section.section; > + > + for (i = 0; i < indent; i++) > + printf (" "); > + if (s) > + printf ("%s\n", s->name); > + else > + printf ("unknown input section\n"); > + > + break; > + > + case lang_output_section_statement_enum: > + os_stat = &curr->output_section_statement; > + for (i = 0; i < indent; i++) > + printf (" "); > + if (r != os_stat->region) > + { > + r = os_stat->region; > + if (r) > + printf ("\nNEW REGION %s\n---\n", r->name_list.name); > + else > + printf ("\nNEW UNKNOWN REGION\n---\n"); > + } > + s = curr->output_section_statement.bfd_section; > + for (i = 0; i < indent; i++) > + printf (" "); > + if (s) > + { > + printf ("%s LMA: 0x%lx VMA: 0x%lx", s->name, s->lma, s->vma); > + if (os_stat->lma_region) > + printf (" LMA region = %s", os_stat->lma_region->name_list.name); > + if (os_stat->region) > + printf (" VMA region = %s", os_stat->region->name_list.name); > + printf ("\n"); > + } > + else > + printf ("unknown output section, curr region vma 0x%lx\n", os_stat->region->current); > + > + dump_sections (&curr->output_section_statement.children, curr->output_section_statement.region, indent + 1); > + break; > + > + case lang_wild_statement_enum: > + for (i = 0; i < indent; i++) > + printf (" "); > + printf ("wild statement\n"); > + dump_sections (&curr->wild_statement.children, r, indent + 1); > + break; > + > + case lang_group_statement_enum: > + dump_sections (&curr->group_statement.children, r, indent + 1); > + break; > + > + case lang_assignment_statement_enum: > + if (1) > + { > + lang_assignment_statement_type *ass; > + > + ass = &curr->assignment_statement; > + for (i = 0; i < indent; i++) > + printf (" "); > + printf ("assignment statement, dst = %s\n", ass->exp->assign.dst); > + } > + break; > + > + default: > + break; > + } > + } > +} > diff --git a/ld/ldlang.c b/ld/ldlang.c > index 4249b3a045..b8d260f780 100644 > --- a/ld/ldlang.c > +++ b/ld/ldlang.c > @@ -1345,6 +1345,12 @@ static lang_memory_region_type *lang_memory_region_list; > static lang_memory_region_type **lang_memory_region_list_tail > = &lang_memory_region_list; > > +lang_memory_region_type * > +get_memory_region_list () > +{ > + return lang_memory_region_list; > +} > + > lang_memory_region_type * > lang_memory_region_lookup (const char *const name, bfd_boolean create) > { > @@ -1798,7 +1804,7 @@ output_prev_sec_find (lang_output_section_statement_type *os) > insert non-alloc note sections among assignments setting end of > image symbols. */ > > -static lang_statement_union_type ** > +lang_statement_union_type ** > insert_os_after (lang_output_section_statement_type *after) > { > lang_statement_union_type **where; > diff --git a/ld/ldlang.h b/ld/ldlang.h > index 196debfa37..631e50d027 100644 > --- a/ld/ldlang.h > +++ b/ld/ldlang.h > @@ -520,6 +520,8 @@ extern struct asneeded_minfo **asneeded_list_tail; > > extern void (*output_bfd_hash_table_free_fn) (struct bfd_link_hash_table *); > > +extern lang_memory_region_type * get_memory_region_list (void); > + > extern void lang_init > (void); > extern void lang_finish > @@ -595,6 +597,9 @@ extern void ldlang_add_file > extern lang_output_section_statement_type *lang_output_section_find_by_flags > (const asection *, flagword, lang_output_section_statement_type **, > lang_match_sec_type_func); > + > +extern lang_statement_union_type ** insert_os_after > +(lang_output_section_statement_type *after); > extern lang_output_section_statement_type *lang_insert_orphan > (asection *, const char *, int, lang_output_section_statement_type *, > struct orphan_save *, etree_type *, lang_statement_list_type *); > diff --git a/ld/testsuite/ld-arm/abind-1.d b/ld/testsuite/ld-arm/abind-1.d > new file mode 100644 > index 0000000000..1b2ad44d56 > --- /dev/null > +++ b/ld/testsuite/ld-arm/abind-1.d > @@ -0,0 +1,49 @@ > +#name: SHF_GNU_ABIND 1 (using default linker script) > +#source: abind-1.s > +#ld: -e _start > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +00008000 t addr_0x8000_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +0000b002 r addr_0xb002 > +#... > +0000b100 t addr_0xb100 > +#... > +0000b200 r addr_0xb200_size_0x1000 > +#... > +0000c402 d addr_0xc402 > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0000e000 b addr_0xe000_size_0x1000 > +#... > +0000f000 b addr_0xf000 > +#pass > diff --git a/ld/testsuite/ld-arm/abind-1.s b/ld/testsuite/ld-arm/abind-1.s > new file mode 100644 > index 0000000000..68183a3bbb > --- /dev/null > +++ b/ld/testsuite/ld-arm/abind-1.s > @@ -0,0 +1,183 @@ > +/* abind-2*.ld linker scripts don't have rules for uniquely named sections. > + This means they will be orphaned which will better test the intermixing of > + .abind and regular sections, instead of just having one large indivisible > + block for each output section. */ > + > +/* Arbitrary sized .data sections. */ > + .section .data.size_0x1,"aw" > + .type data_size_0x1, %object > +data_size_0x1: > + .zero 0x1 > + > + .section .data.size_0x10,"aw" > + .type data_size_0x10, %object > +data_size_0x10: > + .zero 0x10 > + > + .section .data.size_0x80,"aw" > + .type data_size_0x80, %object > +data_size_0x80: > + .zero 0x80 > + > + .section .data.size_0x100,"aw" > + .type data_size_0x100, %object > +data_size_0x100: > + .zero 0x100 > + > + .section .data.size_0x800,"aw" > + .type data_size_0x800, %object > +data_size_0x800: > + .zero 0x800 > + > + .section .data.size_0x1000,"aw" > + .type data_size_0x1000, %object > +data_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .bss sections. */ > + > + .section .bss.size_0x1,"aw",%nobits > + .type bss_size_0x1, %object > +bss_size_0x1: > + .zero 0x1 > + > + .section .bss.size_0x10,"aw",%nobits > + .type bss_size_0x10, %object > +bss_size_0x10: > + .zero 0x10 > + > + .section .bss.size_0x80,"aw",%nobits > + .type bss_size_0x80, %object > +bss_size_0x80: > + .zero 0x80 > + > + .section .bss.size_0x100,"aw",%nobits > + .type bss_size_0x100, %object > +bss_size_0x100: > + .zero 0x100 > + > + .section .bss.size_0x800,"aw",%nobits > + .type bss_size_0x800, %object > +bss_size_0x800: > + .zero 0x800 > + > + .section .bss.size_0x1000,"aw",%nobits > + .type bss_size_0x1000, %object > +bss_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .text sections. */ > + > + .section .text.size_0x1,"ax",%progbits > + .type text_size_0x1, %function > +text_size_0x1: > + .zero 0x1 > + > + .section .text.size_0x10,"ax",%progbits > + .type text_size_0x10, %function > +text_size_0x10: > + .zero 0x10 > + > + .section .text.size_0x80,"ax",%progbits > + .type text_size_0x80, %function > +text_size_0x80: > + .zero 0x80 > + > + .section .text.size_0x100,"ax",%progbits > + .type text_size_0x100, %function > +text_size_0x100: > + .zero 0x100 > + > + .section .text.size_0x800,"ax",%progbits > + .type text_size_0x800, %function > +text_size_0x800: > + .zero 0x800 > + > + .section .text.size_0x1000,"ax",%progbits > + .type text_size_0x1000, %function > +text_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .rodata sections. */ > + > + .section .rodata.size_0x1,"a" > + .type rodata_size_0x1, %object > +rodata_size_0x1: > + .zero 0x1 > + > + .section .rodata.size_0x10,"a" > + .type rodata_size_0x10, %object > +rodata_size_0x10: > + .zero 0x10 > + > + .section .rodata.size_0x80,"a" > + .type rodata_size_0x80, %object > +rodata_size_0x80: > + .zero 0x80 > + > + .section .rodata.size_0x100,"a" > + .type rodata_size_0x100, %object > +rodata_size_0x100: > + .zero 0x100 > + > + .section .rodata.size_0x800,"a" > + .type rodata_size_0x800, %object > +rodata_size_0x800: > + .zero 0x800 > + > + .section .rodata.size_0x1000,"a" > + .type rodata_size_0x1000, %object > +rodata_size_0x1000: > + .zero 0x1000 > + > +/* Start .gnu.abind sections. */ > + > +/* Fix a large section to the start of the region used for the LMA region of > + the .data sections. This will expose any placement issues causing > + overlapping LMAs. */ > + .section .text.addr_0x8000,"axA",%progbits,0x8000 > + .type addr_0x8000, %function > +addr_0x8000_size_0x1000: > + .zero 0x1000 > + > + .section .rodata.addr_0xb002,"aA",0xb002 > + .type addr_0xb002, %object > +addr_0xb002: > + .byte 2 > + > + .section .text.addr_0xb100,"axA",%progbits,0xb100 > + .type addr_0xb100, %function > +addr_0xb100: > + .zero 2 > + > + .section .rodata.addr_0xb200,"aA",0xb200 > + .type addr_0xb200, %object > +addr_0xb200_size_0x1000: > + .zero 0x1000 > + > + .section .data.addr_0xc402,"awA",0xc402 > + .type addr_0xc402, %object > +addr_0xc402: > + .zero 2 > + > + .section .bss.addr_0xe000,"awA",%nobits,0xe000 > + .type addr_0xe000, %object > +addr_0xe000_size_0x1000: > + .zero 0x1000 > + > + .section .bss.addr_0xf000,"awA",%nobits,0x0f000 > + .type addr_0xf000, %object > +addr_0xf000: > + .zero 1 > + > + .section .text._start,"ax",%progbits > + .global _start > + .type _start, %function > +_start: > + .word 0 > + > + .section .text.__run_gnu_abind_init_array,"ax",%progbits > + .global __run_gnu_abind_init_array > + .type __run_gnu_abind_init_array, %function > +__run_gnu_abind_init_array: > + .word 0 > diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp > index 0b47d636df..11b06b28a6 100644 > --- a/ld/testsuite/ld-arm/arm-elf.exp > +++ b/ld/testsuite/ld-arm/arm-elf.exp > @@ -1269,6 +1269,8 @@ run_dump_test "non-contiguous-arm4" > run_dump_test "non-contiguous-arm5" > run_dump_test "non-contiguous-arm6" > > +run_dump_test "abind-1" > + > if { ![istarget "arm*-*-nacl*"] } { > run_dump_test "thumb-plt" > run_dump_test "thumb-plt-got" > diff --git a/ld/testsuite/ld-elf/abind-1.s b/ld/testsuite/ld-elf/abind-1.s > new file mode 100644 > index 0000000000..aa3f1fcf82 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1.s > @@ -0,0 +1,57 @@ > +/* This should get placed before addr_0x8200, at 0x8000. */ > + .section .data.size_0x100,"aw" > + .type size_0x100, %object > +size_0x100: > + .zero 0x100 > + > +/* This should get placed after addr_0x8200. */ > + .section .bss.size_0x150,"aw",%nobits > + .type size_0x150, %object > +size_0x150: > + .zero 0x150 > + > + .section .data.addr_0x8200,"awA",0x8200 > + .type addr_0x8200, %object > +addr_0x8200: > + .short 1 > + > + .section .bss.addr_0x9000,"awA",%nobits,0x9000 > + .type addr_0x9000, %object > +addr_0x9000: > + .zero 1 > + > +/* This should be the last section in the region. */ > + .section .bss.addr_0xa000,"awA",%nobits,0xa000 > + .type addr_0xa000, %object > +addr_0xa000: > + .zero 1 > + > +/* Fix a large section to the start of the region used for the LMA region of > + the .data sections. This will expose any placement issues causing > + overlapping LMAs. */ > + .section .text.addr_0x0,"axA",%progbits,0x0 > + .type addr_0x0, %function > +addr_0x0: > + .zero 0x1000 > + > + .section .text.size_0x500,"ax",%progbits > + .type size_0x500, %function > +size_0x500: > + .zero 0x1000 > + > + .section .rodata.addr_0x1002,"aA",0x1002 > + .type addr_0x1002, %object > +addr_0x1002: > + .byte 2 > + > + .section .text._start,"ax",%progbits > + .global _start > + .type _start, %function > +_start: > + .word 0 > + > + .section .text.__run_gnu_abind_init_array,"ax",%progbits > + .global __run_gnu_abind_init_array > + .type __run_gnu_abind_init_array, %function > +__run_gnu_abind_init_array: > + .word 0 > diff --git a/ld/testsuite/ld-elf/abind-1a.d b/ld/testsuite/ld-elf/abind-1a.d > new file mode 100644 > index 0000000000..1b758fef59 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1a.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1a > +#source: abind-1.s > +#ld: -e _start -T abind-1a.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . size_0x150 > +#... > +0+8200 . addr_0x8200 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1a.ld b/ld/testsuite/ld-elf/abind-1a.ld > new file mode 100644 > index 0000000000..dd3a18ef70 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1a.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + ROM (rx) : ORIGIN = 0x0000, LENGTH = 0x7fff > + RAM (rwx) : ORIGIN = 0x8000, LENGTH = 0x7fff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > ROM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > ROM > + > + .data : > + { > + *(.data .data.*) > + } > RAM AT> ROM > +} > diff --git a/ld/testsuite/ld-elf/abind-1b.d b/ld/testsuite/ld-elf/abind-1b.d > new file mode 100644 > index 0000000000..41c926529a > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1b.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1b > +#source: abind-1.s > +#ld: -e _start -T abind-1b.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . size_0x100 > +#... > +0+8200 . addr_0x8200 > +#... > +[0-9a-f]+ . size_0x150 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1b.ld b/ld/testsuite/ld-elf/abind-1b.ld > new file mode 100644 > index 0000000000..99f9163b7f > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1b.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + ROM (rx) : ORIGIN = 0x0000, LENGTH = 0x6fff > + RAM (rwx) : ORIGIN = 0x8000, LENGTH = 0x6fff > +} > + > +SECTIONS > +{ > + .data : > + { > + *(.data .data.*) > + } > RAM AT> ROM > + > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > ROM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > ROM > +} > diff --git a/ld/testsuite/ld-elf/abind-1c.d b/ld/testsuite/ld-elf/abind-1c.d > new file mode 100644 > index 0000000000..740e6b112d > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1c.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1c > +#source: abind-1.s > +#ld: -e _start -T abind-1c.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . size_0x150 > +#... > +0+8200 . addr_0x8200 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1c.ld b/ld/testsuite/ld-elf/abind-1c.ld > new file mode 100644 > index 0000000000..1587ef028e > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1c.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + ROM (rx) : ORIGIN = 0x0000, LENGTH = 0x6fff > + RAM (rwx) : ORIGIN = 0x8000, LENGTH = 0x6fff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > ROM > + > + .data : > + { > + *(.data .data.*) > + } > RAM AT> ROM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > ROM > +} > diff --git a/ld/testsuite/ld-elf/abind-1d.d b/ld/testsuite/ld-elf/abind-1d.d > new file mode 100644 > index 0000000000..9c2e64dc4c > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1d.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1d > +#source: abind-1.s > +#ld: -e _start -T abind-1d.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . size_0x150 > +#... > +0+8200 . addr_0x8200 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1d.ld b/ld/testsuite/ld-elf/abind-1d.ld > new file mode 100644 > index 0000000000..852e03e645 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1d.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + ROM (rx) : ORIGIN = 0x0000, LENGTH = 0x6fff > + RAM (rwx) : ORIGIN = 0x8000, LENGTH = 0x6fff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .data : > + { > + *(.data .data.*) > + } > RAM AT> ROM > + > + .text : > + { > + *(.text .text.*) > + } > ROM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > ROM > +} > diff --git a/ld/testsuite/ld-elf/abind-1e.d b/ld/testsuite/ld-elf/abind-1e.d > new file mode 100644 > index 0000000000..ac1a78654f > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1e.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1e (No LMA region) > +#source: abind-1.s > +#ld: -e _start -T abind-1e.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x150 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +0+8200 . addr_0x8200 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1e.ld b/ld/testsuite/ld-elf/abind-1e.ld > new file mode 100644 > index 0000000000..58b3dc075a > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1e.ld > @@ -0,0 +1,27 @@ > +MEMORY > +{ > + RAM (rwx) : ORIGIN = 0x0000, LENGTH = 0xefff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .data : > + { > + *(.data .data.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > RAM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-1f.d b/ld/testsuite/ld-elf/abind-1f.d > new file mode 100644 > index 0000000000..2981a4e6d1 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1f.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1f (Placement in other region) > +#source: abind-1.s > +#ld: -e _start -T abind-1f.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x150 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +0+8200 . addr_0x8200 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1f.ld b/ld/testsuite/ld-elf/abind-1f.ld > new file mode 100644 > index 0000000000..7a655e0262 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1f.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + RAM (rwx) : ORIGIN = 0x0000, LENGTH = 0x9fff > + VECT : ORIGIN = 0xa000, LENGTH = 0x4 > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .data : > + { > + *(.data .data.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > RAM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-1g.d b/ld/testsuite/ld-elf/abind-1g.d > new file mode 100644 > index 0000000000..90807c4951 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1g.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1g (Placement outside region) > +#source: abind-1.s > +#ld: -e _start -T abind-1g.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x150 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +0+8200 . addr_0x8200 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1g.ld b/ld/testsuite/ld-elf/abind-1g.ld > new file mode 100644 > index 0000000000..8749d74626 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1g.ld > @@ -0,0 +1,27 @@ > +MEMORY > +{ > + RAM (rwx) : ORIGIN = 0x0000, LENGTH = 0x9fff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .data : > + { > + *(.data .data.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > RAM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-1h.d b/ld/testsuite/ld-elf/abind-1h.d > new file mode 100644 > index 0000000000..a17f5d47a0 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1h.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1h (No flags set on region) > +#source: abind-1.s > +#ld: -e _start -T abind-1h.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x150 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +0+8200 . addr_0x8200 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1h.ld b/ld/testsuite/ld-elf/abind-1h.ld > new file mode 100644 > index 0000000000..8092bb40d6 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1h.ld > @@ -0,0 +1,27 @@ > +MEMORY > +{ > + RAM : ORIGIN = 0x0000, LENGTH = 0xafff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > RAM > + > + .data : > + { > + *(.data .data.*) > + } > RAM > + > + .text : > + { > + *(.text .text.*) > + } > RAM > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-1i.d b/ld/testsuite/ld-elf/abind-1i.d > new file mode 100644 > index 0000000000..17696c3760 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1i.d > @@ -0,0 +1,27 @@ > +#name: SHF_GNU_ABIND 1i (No memory regions) > +#source: abind-1.s > +#ld: -e _start -T abind-1i.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 . addr_0x0 > +#... > +0+1002 . addr_0x1002 > +#... > +[0-9a-f]+ . size_0x150 > +#... > +[0-9a-f]+ . size_0x100 > +#... > +[0-9a-f]+ . size_0x500 > +#... > +[0-9a-f]+ . _start > +#... > +[0-9a-f]+ . __run_gnu_abind_init_array > +#... > +0+8200 . addr_0x8200 > +#... > +0+9000 . addr_0x9000 > +#... > +0+a000 . addr_0xa000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-1i.ld b/ld/testsuite/ld-elf/abind-1i.ld > new file mode 100644 > index 0000000000..9b763c7387 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-1i.ld > @@ -0,0 +1,22 @@ > +SECTIONS > +{ > + .bss : > + { > + *(.bss .bss.*) > + } > + > + .data : > + { > + *(.data .data.*) > + } > + > + .text : > + { > + *(.text .text.*) > + } > + > + .rodata : > + { > + *(.rodata .rodata.*) > + } > +} > diff --git a/ld/testsuite/ld-elf/abind-2.s b/ld/testsuite/ld-elf/abind-2.s > new file mode 100644 > index 0000000000..75777e4817 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2.s > @@ -0,0 +1,183 @@ > +/* abind-2*.ld linker scripts don't have rules for uniquely named sections. > + This means they will be orphaned which will better test the intermixing of > + .abind and regular sections, instead of just having one large indivisible > + block for each output section. */ > + > +/* Arbitrary sized .data sections. */ > + .section .data.size_0x1,"aw" > + .type data_size_0x1, %object > +data_size_0x1: > + .zero 0x1 > + > + .section .data.size_0x10,"aw" > + .type data_size_0x10, %object > +data_size_0x10: > + .zero 0x10 > + > + .section .data.size_0x80,"aw" > + .type data_size_0x80, %object > +data_size_0x80: > + .zero 0x80 > + > + .section .data.size_0x100,"aw" > + .type data_size_0x100, %object > +data_size_0x100: > + .zero 0x100 > + > + .section .data.size_0x800,"aw" > + .type data_size_0x800, %object > +data_size_0x800: > + .zero 0x800 > + > + .section .data.size_0x1000,"aw" > + .type data_size_0x1000, %object > +data_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .bss sections. */ > + > + .section .bss.size_0x1,"aw",%nobits > + .type bss_size_0x1, %object > +bss_size_0x1: > + .zero 0x1 > + > + .section .bss.size_0x10,"aw",%nobits > + .type bss_size_0x10, %object > +bss_size_0x10: > + .zero 0x10 > + > + .section .bss.size_0x80,"aw",%nobits > + .type bss_size_0x80, %object > +bss_size_0x80: > + .zero 0x80 > + > + .section .bss.size_0x100,"aw",%nobits > + .type bss_size_0x100, %object > +bss_size_0x100: > + .zero 0x100 > + > + .section .bss.size_0x800,"aw",%nobits > + .type bss_size_0x800, %object > +bss_size_0x800: > + .zero 0x800 > + > + .section .bss.size_0x1000,"aw",%nobits > + .type bss_size_0x1000, %object > +bss_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .text sections. */ > + > + .section .text.size_0x1,"ax",%progbits > + .type text_size_0x1, %function > +text_size_0x1: > + .zero 0x1 > + > + .section .text.size_0x10,"ax",%progbits > + .type text_size_0x10, %function > +text_size_0x10: > + .zero 0x10 > + > + .section .text.size_0x80,"ax",%progbits > + .type text_size_0x80, %function > +text_size_0x80: > + .zero 0x80 > + > + .section .text.size_0x100,"ax",%progbits > + .type text_size_0x100, %function > +text_size_0x100: > + .zero 0x100 > + > + .section .text.size_0x800,"ax",%progbits > + .type text_size_0x800, %function > +text_size_0x800: > + .zero 0x800 > + > + .section .text.size_0x1000,"ax",%progbits > + .type text_size_0x1000, %function > +text_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .rodata sections. */ > + > + .section .rodata.size_0x1,"a" > + .type rodata_size_0x1, %object > +rodata_size_0x1: > + .zero 0x1 > + > + .section .rodata.size_0x10,"a" > + .type rodata_size_0x10, %object > +rodata_size_0x10: > + .zero 0x10 > + > + .section .rodata.size_0x80,"a" > + .type rodata_size_0x80, %object > +rodata_size_0x80: > + .zero 0x80 > + > + .section .rodata.size_0x100,"a" > + .type rodata_size_0x100, %object > +rodata_size_0x100: > + .zero 0x100 > + > + .section .rodata.size_0x800,"a" > + .type rodata_size_0x800, %object > +rodata_size_0x800: > + .zero 0x800 > + > + .section .rodata.size_0x1000,"a" > + .type rodata_size_0x1000, %object > +rodata_size_0x1000: > + .zero 0x1000 > + > +/* Start .gnu.abind sections. */ > + > +/* Fix a large section to the start of the region used for the LMA region of > + the .data sections. This will expose any placement issues causing > + overlapping LMAs. */ > + .section .text.addr_0x0,"axA",%progbits,0x0 > + .type addr_0x0, %function > +addr_0x0_size_0x1000: > + .zero 0x1000 > + > + .section .rodata.addr_0x1002,"aA",0x1002 > + .type addr_0x1002, %object > +addr_0x1002: > + .byte 2 > + > + .section .text.addr_0x2000,"axA",%progbits,0x2000 > + .type addr_0x2000, %function > +addr_0x2000: > + .zero 2 > + > + .section .rodata.addr_0x3002,"aA",0x3002 > + .type addr_0x3002, %object > +addr_0x3002_size_0x1000: > + .zero 0x1000 > + > + .section .data.addr_0x8000,"awA",0x8000 > + .type addr_0x8000, %object > +addr_0x8000: > + .zero 2 > + > + .section .bss.addr_0x9000,"awA",%nobits,0x9000 > + .type addr_0x9000, %object > +addr_0x9000_size_0x1000: > + .zero 0x1000 > + > + .section .bss.addr_0xd000,"awA",%nobits,0xd000 > + .type addr_0xd000, %object > +addr_0xd000: > + .zero 1 > + > + .section .text._start,"ax",%progbits > + .global _start > + .type _start, %function > +_start: > + .word 0 > + > + .section .text.__run_gnu_abind_init_array,"ax",%progbits > + .global __run_gnu_abind_init_array > + .type __run_gnu_abind_init_array, %function > +__run_gnu_abind_init_array: > + .word 0 > diff --git a/ld/testsuite/ld-elf/abind-2a.d b/ld/testsuite/ld-elf/abind-2a.d > new file mode 100644 > index 0000000000..ec247ac951 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2a.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2a > +#source: abind-2.s > +#ld: -e _start -T abind-2a.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+8000 d addr_0x8000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2a.ld b/ld/testsuite/ld-elf/abind-2a.ld > new file mode 100644 > index 0000000000..517366f395 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2a.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + ROM (rx) : ORIGIN = 0x0000, LENGTH = 0x7fff > + RAM (rwx) : ORIGIN = 0x8000, LENGTH = 0x7fff > +} > + > +SECTIONS > +{ > + .text : > + { > + *(.text) > + } > ROM > + > + .rodata : > + { > + *(.rodata) > + } > ROM > + > + .data : > + { > + *(.data) > + } > RAM AT> ROM > + > + .bss : > + { > + *(.bss) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-2b.d b/ld/testsuite/ld-elf/abind-2b.d > new file mode 100644 > index 0000000000..66057ab3bd > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2b.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2b > +#source: abind-2.s > +#ld: -e _start -T abind-2b.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+8000 d addr_0x8000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2b.ld b/ld/testsuite/ld-elf/abind-2b.ld > new file mode 100644 > index 0000000000..e180fabedb > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2b.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + ROM (rx) : ORIGIN = 0x0000, LENGTH = 0x7fff > + RAM (rwx) : ORIGIN = 0x8000, LENGTH = 0x7fff > +} > + > +SECTIONS > +{ > + .text : > + { > + *(.text) > + } > ROM > + > + .rodata : > + { > + *(.rodata) > + } > ROM > + > + .bss : > + { > + *(.bss) > + } > RAM > + > + .data : > + { > + *(.data) > + } > RAM AT> ROM > +} > diff --git a/ld/testsuite/ld-elf/abind-2c.d b/ld/testsuite/ld-elf/abind-2c.d > new file mode 100644 > index 0000000000..74f62a36f1 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2c.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2c > +#source: abind-2.s > +#ld: -e _start -T abind-2c.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +0+8000 d addr_0x8000 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2c.ld b/ld/testsuite/ld-elf/abind-2c.ld > new file mode 100644 > index 0000000000..3c553f4b31 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2c.ld > @@ -0,0 +1,27 @@ > +MEMORY > +{ > + RAM (rwx) : ORIGIN = 0x0000, LENGTH = 0xefff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss) > + } > RAM > + > + .data : > + { > + *(.data) > + } > RAM > + > + .text : > + { > + *(.text) > + } > RAM > + > + .rodata : > + { > + *(.rodata) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-2d.d b/ld/testsuite/ld-elf/abind-2d.d > new file mode 100644 > index 0000000000..1fb480843f > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2d.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2d > +#source: abind-2.s > +#ld: -e _start -T abind-2d.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +0+8000 d addr_0x8000 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2d.ld b/ld/testsuite/ld-elf/abind-2d.ld > new file mode 100644 > index 0000000000..00b375bfbe > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2d.ld > @@ -0,0 +1,28 @@ > +MEMORY > +{ > + RAM (rwx) : ORIGIN = 0x0000, LENGTH = 0xcfff > + VECT : ORIGIN = 0xd000, LENGTH = 0x4 > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss) > + } > RAM > + > + .data : > + { > + *(.data) > + } > RAM > + > + .text : > + { > + *(.text) > + } > RAM > + > + .rodata : > + { > + *(.rodata) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-2e.d b/ld/testsuite/ld-elf/abind-2e.d > new file mode 100644 > index 0000000000..ff15f34de8 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2e.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2e > +#source: abind-2.s > +#ld: -e _start -T abind-2e.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +0+8000 d addr_0x8000 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2e.ld b/ld/testsuite/ld-elf/abind-2e.ld > new file mode 100644 > index 0000000000..b1bb54b3a4 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2e.ld > @@ -0,0 +1,27 @@ > +MEMORY > +{ > + RAM (rwx) : ORIGIN = 0x0000, LENGTH = 0xcfff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss) > + } > RAM > + > + .data : > + { > + *(.data) > + } > RAM > + > + .text : > + { > + *(.text) > + } > RAM > + > + .rodata : > + { > + *(.rodata) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-2f.d b/ld/testsuite/ld-elf/abind-2f.d > new file mode 100644 > index 0000000000..8a59b5da79 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2f.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2f > +#source: abind-2.s > +#ld: -e _start -T abind-2f.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +0+8000 d addr_0x8000 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2f.ld b/ld/testsuite/ld-elf/abind-2f.ld > new file mode 100644 > index 0000000000..4867878538 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2f.ld > @@ -0,0 +1,27 @@ > +MEMORY > +{ > + RAM : ORIGIN = 0x0000, LENGTH = 0xdfff > +} > + > +SECTIONS > +{ > + .bss : > + { > + *(.bss) > + } > RAM > + > + .data : > + { > + *(.data) > + } > RAM > + > + .text : > + { > + *(.text) > + } > RAM > + > + .rodata : > + { > + *(.rodata) > + } > RAM > +} > diff --git a/ld/testsuite/ld-elf/abind-2g.d b/ld/testsuite/ld-elf/abind-2g.d > new file mode 100644 > index 0000000000..7084f5fcee > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2g.d > @@ -0,0 +1,73 @@ > +#name: SHF_GNU_ABIND 2g > +#source: abind-2.s > +#ld: -e _start -T abind-2g.ld > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+0000 t addr_0x0_size_0x1000 > +#... > +[0-9a-f]+ . bss_size_0x1 > +#... > +0+1002 r addr_0x1002 > +#... > +[0-9a-f]+ . bss_size_0x10 > +#... > +[0-9a-f]+ . bss_size_0x80 > +#... > +[0-9a-f]+ . bss_size_0x100 > +#... > +[0-9a-f]+ . bss_size_0x800 > +#... > +0+2000 t addr_0x2000 > +#... > +[0-9a-f]+ . bss_size_0x1000 > +#... > +0+3002 r addr_0x3002_size_0x1000 > +#... > +[0-9a-f]+ . data_size_0x1 > +#... > +[0-9a-f]+ . data_size_0x10 > +#... > +[0-9a-f]+ . data_size_0x80 > +#... > +[0-9a-f]+ . data_size_0x100 > +#... > +[0-9a-f]+ . data_size_0x800 > +#... > +[0-9a-f]+ . data_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +#... > +[0-9a-f]+ . text_size_0x10 > +#... > +[0-9a-f]+ . text_size_0x80 > +#... > +[0-9a-f]+ . text_size_0x100 > +#... > +[0-9a-f]+ . text_size_0x800 > +#... > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +#... > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +[0-9a-f]+ . rodata_size_0x1 > +#... > +[0-9a-f]+ . rodata_size_0x10 > +#... > +[0-9a-f]+ . rodata_size_0x80 > +#... > +[0-9a-f]+ . rodata_size_0x100 > +#... > +[0-9a-f]+ . rodata_size_0x800 > +#... > +0+8000 d addr_0x8000 > +#... > +0+9000 b addr_0x9000_size_0x1000 > +#... > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+d000 b addr_0xd000 > +#pass > diff --git a/ld/testsuite/ld-elf/abind-2g.ld b/ld/testsuite/ld-elf/abind-2g.ld > new file mode 100644 > index 0000000000..2a9be2b5c8 > --- /dev/null > +++ b/ld/testsuite/ld-elf/abind-2g.ld > @@ -0,0 +1,22 @@ > +SECTIONS > +{ > + .bss : > + { > + *(.bss) > + } > + > + .data : > + { > + *(.data) > + } > + > + .text : > + { > + *(.text) > + } > + > + .rodata : > + { > + *(.rodata) > + } > +} > diff --git a/ld/testsuite/ld-msp430-elf/location-1.d b/ld/testsuite/ld-msp430-elf/location-1.d > new file mode 100644 > index 0000000000..9a23431033 > --- /dev/null > +++ b/ld/testsuite/ld-msp430-elf/location-1.d > @@ -0,0 +1,23 @@ > +# Test that text, rodata, data and bss locsyms get placed at the correct > +# addresses. > +# The variable "either" should be placed in between the .data sections. > +# > +#name: SMK_LOCATION data meta-information > +#ld: -e _start > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +00000510 . loc510_data > +00000520 . loc520_data > +000005f1 . loc5f1_data > +#... > +[0-9a-f]+ . either > +#... > +00000790 . loc790_data > +00000808 . loc808_data > +00000850 . loc850_bss > +#... > +00009000 . loc9000_text > +0000910a . loc910a_rodata > +#pass > diff --git a/ld/testsuite/ld-msp430-elf/location-1.s b/ld/testsuite/ld-msp430-elf/location-1.s > new file mode 100644 > index 0000000000..83d179d281 > --- /dev/null > +++ b/ld/testsuite/ld-msp430-elf/location-1.s > @@ -0,0 +1,98 @@ > + .global arr_1 > + .section .data.arr_1,"aw" > + .type arr_1, %object > +arr_1: > + .zero 80 > + > + .global arr_2 > + .section .data.arr_2,"aw" > + .type arr_2, %object > +arr_2: > + .zero 80 > + > + .global arr_3 > + .section .data.arr_3,"aw" > + .type arr_3, %object > +arr_3: > + .zero 80 > + > + .global arr_4 > + .section .data.arr_4,"aw" > + .type arr_4, %object > +arr_4: > + .zero 80 > + > +/* > + .global const_arr_1 > + .section .rodata.const_arr_1,"a" > + .type const_arr_1, %object > +const_arr_1: > + .zero 80 > + */ > + > + > + .global loc808_data > + .section .data.loc808_data,"awA",0x808 > + .type loc808_data, %object > +loc808_data: > + .short 2056 > + > + .global loc510_data > + .section .data.loc510_data,"awA",0x510 > + .type loc510_data, %object > +loc510_data: > + .byte 81 > + > + .global loc520_data > + .section .data.loc520_data,"awA",0x520 > + .type loc520_data, %object > +loc520_data: > + .byte 82 > + > + .global loc790_data > + .section .data.loc790_data,"awA",0x790 > + .type loc790_data, %object > +loc790_data: > + .byte 114 > + > + .global loc5f1_data > + .section .data.loc5f1_data,"awA",0x5f1 > + .type loc5f1_data, %object > +loc5f1_data: > + .byte 95 > + > + .section .text.loc9000_text,"axA",%progbits,0x9000 > + .global loc9000_text > + .type loc9000_text, %function > +loc9000_text: > + .word 0 > + > + .global loc910a_rodata > + .section .rodata.loc910a_rodata,"aA",0x910a > + .type loc910a_rodata, %object > +loc910a_rodata: > + .byte 2 > + > + .global loc850_bss > + .section .bss.loc850_bss,"awA",%nobits,0x850 > + .type loc850_bss, %object > +loc850_bss: > + .zero 1 > + > + .global normal_bss > + .section .bss.normal_bss,"aw",%nobits > + .type normal_bss, %object > +normal_bss: > + .zero 1 > + > + .global either > + .section .either.data,"aw" > + .type either, %object > +either: > + .byte 1 > + > + .section .text._start,"ax",%progbits > + .global _start > + .type _start, %function > +_start: > + .word 0 > diff --git a/ld/testsuite/ld-msp430-elf/location-2.d b/ld/testsuite/ld-msp430-elf/location-2.d > new file mode 100644 > index 0000000000..87f3d4555e > --- /dev/null > +++ b/ld/testsuite/ld-msp430-elf/location-2.d > @@ -0,0 +1,30 @@ > +# Test that relaxation of branch instructions to jumps does not interfere > +# with accurrate placement of sections. > +# Before location placement, the BR instructions are all close enough to their > +# destination such that they can be relaxed to JMP. However, after placement > +# of the sections, some of the JMP will now be out of range, so check that they > +# get relaxed back to a BR (tested by the fact there are no relocation > +# overflows), and that the functions still get placed at the > +# correct address. > +#name: SMK_LOCATION meta-information placement after relaxation > +#ld: -e _start > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+8000 . fn_8000 > +#... > +0+8200 . fn_8200 > +#... > +0+8500 . fn_dst > +#... > +0+8600 . fn_8600 > +#... > +0+8700 . fn_8700 > +#... > +0+8a00 . fn_8a00 > +#... > +0+9000 . fn_9000 > +#... > +0+910a . loc910a_rodata > +#pass > diff --git a/ld/testsuite/ld-msp430-elf/location-2.s b/ld/testsuite/ld-msp430-elf/location-2.s > new file mode 100644 > index 0000000000..0c278a1f78 > --- /dev/null > +++ b/ld/testsuite/ld-msp430-elf/location-2.s > @@ -0,0 +1,76 @@ > + .global loc910a_rodata > + .section .rodata.loc910a_rodata,"a" > + .type loc910a_rodata, @object > +loc910a_rodata: > + .byte 2 > + .location 0x910a > + > + .section .text.fn_8700,"ax",@progbits > + .global fn_8700 > + .type fn_8700, @function > +fn_8700: > + br #fn_dst > + br #fn_9000 > + NOP > + RET > + .section .text.fn_8a00,"ax",@progbits > + .global fn_8a00 > + .type fn_8a00, @function > +fn_8a00: > + br #fn_dst > + br #fn_9000 > + NOP > + RET > + .section .text.fn_8600,"ax",@progbits > + .global fn_8600 > + .type fn_8600, @function > +fn_8600: > + br #fn_dst > + br #fn_9000 > + NOP > + RET > + .section .text.fn_8000,"ax",@progbits > + .global fn_8000 > + .type fn_8000, @function > +fn_8000: > + br #fn_dst > + br #fn_9000 > + NOP > + RET > + .section .text.fn_8200,"ax",@progbits > + .global fn_8200 > + .type fn_8200, @function > +fn_8200: > + br #fn_dst > + br #fn_9000 > + NOP > + RET > + .section .text.fn_9000,"ax",@progbits > + .global fn_9000 > + .type fn_9000, @function > +fn_9000: > + br #fn_dst > + NOP > + RET > + .section .text.fn_dst,"ax",@progbits > + .global fn_dst > + .type fn_dst, @function > +fn_dst: > + add r12, r12 > + NOP > + RET > + .location 0x8000, .text.fn_8000 > + .location 0x8500, .text.fn_dst > + .location 0x8200, .text.fn_8200 > + .location 0x9000, .text.fn_9000 > + .location 0x8600, .text.fn_8600 > + .location 0x8700, .text.fn_8700 > + .location 0x8a00, .text.fn_8a00 > + .section .text._start,"ax",@progbits > + .global _start > + .type _start, @function > +_start: > + CALL #fn_8000 > + MOV.B #0, R12 > + .refsym __crt0_call_exit > + RET > diff --git a/ld/testsuite/ld-msp430-elf/location-3.d b/ld/testsuite/ld-msp430-elf/location-3.d > new file mode 100644 > index 0000000000..0a2becf6fc > --- /dev/null > +++ b/ld/testsuite/ld-msp430-elf/location-3.d > @@ -0,0 +1,10 @@ > +# Test that a text locsym in a random section still gets placed. > +# > +#name: Orphaned location section > +#ld: -e _start > +#notarget: ![supports_gnu_osabi] > +#nm : -n > + > +#... > +00009100 . loc9100_text > +#pass > diff --git a/ld/testsuite/ld-msp430-elf/location-3.s b/ld/testsuite/ld-msp430-elf/location-3.s > new file mode 100644 > index 0000000000..2a2e970933 > --- /dev/null > +++ b/ld/testsuite/ld-msp430-elf/location-3.s > @@ -0,0 +1,12 @@ > + .section .faketext,"ax",%progbits > + .global loc9100_text > + .type loc9100_text, %function > +loc9100_text: > + .word 0 > + .location 0x9100 > + > + .section .text._start,"ax",%progbits > + .global _start > + .type _start, %function > +_start: > + .word 0 > diff --git a/ld/testsuite/ld-msp430-elf/msp430-elf.exp b/ld/testsuite/ld-msp430-elf/msp430-elf.exp > index 875b413c14..22d476a4a5 100644 > --- a/ld/testsuite/ld-msp430-elf/msp430-elf.exp > +++ b/ld/testsuite/ld-msp430-elf/msp430-elf.exp > @@ -190,6 +190,10 @@ run_ld_link_tests $msp430eithershuffletests > run_ld_link_tests $msp430warntests > > run_dump_test valid-map > +run_dump_test location-1 > +run_dump_test location-2 > +run_dump_test location-3 > + > run_ld_link_tests {{ "Check no reloc overflow with #lo and data in the upper region" > "-m msp430X" "" "" {reloc-lo-430x.s} {} "reloc-lo-430x"}} > run_ld_link_tests {{ "Check .upper prefixed input sections can be placed" > diff --git a/ld/testsuite/ld-x86-64/abind-1.d b/ld/testsuite/ld-x86-64/abind-1.d > new file mode 100644 > index 0000000000..33e91e7c51 > --- /dev/null > +++ b/ld/testsuite/ld-x86-64/abind-1.d > @@ -0,0 +1,54 @@ > +#name: SHF_GNU_ABIND 1 (using default linker script) > +#source: abind-1.s > +#ld: -e _start > +#notarget: ![supports_gnu_osabi] > +#nm: -n > + > +#... > +0+400000 t addr_0x400000_size_0x1000 > +#... > +[0-9a-f]+ . text_size_0x1 > +[0-9a-f]+ . text_size_0x10 > +[0-9a-f]+ . text_size_0x80 > +[0-9a-f]+ . text_size_0x100 > +[0-9a-f]+ . text_size_0x800 > +[0-9a-f]+ . text_size_0x1000 > +#... > +[0-9a-f]+ T _start > +[0-9a-f]+ T __run_gnu_abind_init_array > +#... > +0+404002 r addr_0x404002 > +0+406100 t addr_0x406100 > +#... > +[0-9a-f]+ . rodata_size_0x1 > +[0-9a-f]+ . rodata_size_0x10 > +[0-9a-f]+ . rodata_size_0x80 > +[0-9a-f]+ . rodata_size_0x100 > +[0-9a-f]+ . rodata_size_0x800 > +[0-9a-f]+ . rodata_size_0x1000 > +#... > +0+40b200 r addr_0x40b200_size_0x1000 > +#... > +0+40c402 d addr_0x40c402 > +#... > +[0-9a-f]+ . data_size_0x1 > +[0-9a-f]+ . data_size_0x10 > +[0-9a-f]+ . data_size_0x80 > +[0-9a-f]+ . data_size_0x100 > +[0-9a-f]+ . data_size_0x800 > +[0-9a-f]+ . data_size_0x1000 > +#... > +0+40e000 b addr_0x40e000_size_0x1000 > +#... > +0+40f000 b addr_0x40f000 > +#... > +[0-9a-f]+ . __bss_start > +[0-9a-f]+ . _edata > +#... > +[0-9a-f]+ . bss_size_0x1 > +[0-9a-f]+ . bss_size_0x10 > +[0-9a-f]+ . bss_size_0x80 > +[0-9a-f]+ . bss_size_0x100 > +[0-9a-f]+ . bss_size_0x800 > +[0-9a-f]+ . bss_size_0x1000 > +#pass > diff --git a/ld/testsuite/ld-x86-64/abind-1.s b/ld/testsuite/ld-x86-64/abind-1.s > new file mode 100644 > index 0000000000..c7068c7581 > --- /dev/null > +++ b/ld/testsuite/ld-x86-64/abind-1.s > @@ -0,0 +1,175 @@ > +/* Arbitrary sized .data sections. */ > + .section .data.size_0x1,"aw" > + .type data_size_0x1, %object > +data_size_0x1: > + .zero 0x1 > + > + .section .data.size_0x10,"aw" > + .type data_size_0x10, %object > +data_size_0x10: > + .zero 0x10 > + > + .section .data.size_0x80,"aw" > + .type data_size_0x80, %object > +data_size_0x80: > + .zero 0x80 > + > + .section .data.size_0x100,"aw" > + .type data_size_0x100, %object > +data_size_0x100: > + .zero 0x100 > + > + .section .data.size_0x800,"aw" > + .type data_size_0x800, %object > +data_size_0x800: > + .zero 0x800 > + > + .section .data.size_0x1000,"aw" > + .type data_size_0x1000, %object > +data_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .bss sections. */ > + > + .section .bss.size_0x1,"aw",%nobits > + .type bss_size_0x1, %object > +bss_size_0x1: > + .zero 0x1 > + > + .section .bss.size_0x10,"aw",%nobits > + .type bss_size_0x10, %object > +bss_size_0x10: > + .zero 0x10 > + > + .section .bss.size_0x80,"aw",%nobits > + .type bss_size_0x80, %object > +bss_size_0x80: > + .zero 0x80 > + > + .section .bss.size_0x100,"aw",%nobits > + .type bss_size_0x100, %object > +bss_size_0x100: > + .zero 0x100 > + > + .section .bss.size_0x800,"aw",%nobits > + .type bss_size_0x800, %object > +bss_size_0x800: > + .zero 0x800 > + > + .section .bss.size_0x1000,"aw",%nobits > + .type bss_size_0x1000, %object > +bss_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .text sections. */ > + > + .section .text.size_0x1,"ax",%progbits > + .type text_size_0x1, %function > +text_size_0x1: > + .zero 0x1 > + > + .section .text.size_0x10,"ax",%progbits > + .type text_size_0x10, %function > +text_size_0x10: > + .zero 0x10 > + > + .section .text.size_0x80,"ax",%progbits > + .type text_size_0x80, %function > +text_size_0x80: > + .zero 0x80 > + > + .section .text.size_0x100,"ax",%progbits > + .type text_size_0x100, %function > +text_size_0x100: > + .zero 0x100 > + > + .section .text.size_0x800,"ax",%progbits > + .type text_size_0x800, %function > +text_size_0x800: > + .zero 0x800 > + > + .section .text.size_0x1000,"ax",%progbits > + .type text_size_0x1000, %function > +text_size_0x1000: > + .zero 0x1000 > + > +/* Arbitrary sized .rodata sections. */ > + > + .section .rodata.size_0x1,"a" > + .type rodata_size_0x1, %object > +rodata_size_0x1: > + .zero 0x1 > + > + .section .rodata.size_0x10,"a" > + .type rodata_size_0x10, %object > +rodata_size_0x10: > + .zero 0x10 > + > + .section .rodata.size_0x80,"a" > + .type rodata_size_0x80, %object > +rodata_size_0x80: > + .zero 0x80 > + > + .section .rodata.size_0x100,"a" > + .type rodata_size_0x100, %object > +rodata_size_0x100: > + .zero 0x100 > + > + .section .rodata.size_0x800,"a" > + .type rodata_size_0x800, %object > +rodata_size_0x800: > + .zero 0x800 > + > + .section .rodata.size_0x1000,"a" > + .type rodata_size_0x1000, %object > +rodata_size_0x1000: > + .zero 0x1000 > + > +/* Start .gnu.abind sections. */ > + > + .section .text.addr_0x400000,"axA",%progbits,0x400000 > + .type addr_0x400000, %function > +addr_0x400000_size_0x1000: > + .zero 0x1000 > + > + .section .rodata.addr_0x404002,"aA",0x404002 > + .type addr_0x404002, %object > +addr_0x404002: > + .byte 2 > + > + .section .text.addr_0x406100,"axA",%progbits,0x406100 > + .type addr_0x406100, %function > +addr_0x406100: > + .zero 2 > + > + .section .rodata.addr_0x40b200,"aA",0x40b200 > + .type addr_0x40b200, %object > +addr_0x40b200_size_0x1000: > + .zero 0x1000 > + > + .section .data.addr_0x40c402,"awA",0x40c402 > + .type addr_0x40c402, %object > +addr_0x40c402: > + .zero 2 > + > + .section .bss.addr_0x40e000,"awA",%nobits,0x40e000 > + .type addr_0x40e000, %object > +addr_0x40e000_size_0x1000: > + .zero 0x1000 > + > + .section .bss.addr_0x40f000,"awA",%nobits,0x40f000 > + .type addr_0x40f000, %object > +addr_0x40f000: > + .zero 1 > + > + .section .text._start,"ax",%progbits > + .global _start > + .type _start, %function > +_start: > + .word 0 > + > + .section .text.__run_gnu_abind_init_array,"ax",%progbits > + .global __run_gnu_abind_init_array > + .type __run_gnu_abind_init_array, %function > +__run_gnu_abind_init_array: > + .word 0 > diff --git a/ld/testsuite/ld-x86-64/x86-64.exp b/ld/testsuite/ld-x86-64/x86-64.exp > index 59cad54a79..5f61135ccb 100644 > --- a/ld/testsuite/ld-x86-64/x86-64.exp > +++ b/ld/testsuite/ld-x86-64/x86-64.exp > @@ -245,6 +245,7 @@ if { ![ld_link $ld tmpdir/$test "-m$emul tmpdir/${test}a.o tmpdir/${test}b.o"] } > } > } > > +run_dump_test "abind-1" > run_dump_test "abs" > run_dump_test "abs-k1om" > run_dump_test "abs-l1om" > -- > 2.28.0 >