From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr1-x42a.google.com (mail-wr1-x42a.google.com [IPv6:2a00:1450:4864:20::42a]) by sourceware.org (Postfix) with ESMTPS id BA1333857C43 for ; Tue, 20 Oct 2020 10:06:01 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org BA1333857C43 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-wr1-x42a.google.com with SMTP id e17so1373177wru.12 for ; Tue, 20 Oct 2020 03:06:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mime-version:content-disposition; bh=9tX/Z40xttowv6FIAiBrxFebJVgKU/Ic4x46Vfc+GD4=; b=DpYNFJVcya9f+p2DSX1jaSfVEUNF1t1XyBELnSv40Y6KcsYc7P71wRrvejwKS4d4WU nB8UkiNykXOOUcoSsXKKDOu0H/aLAZCCbr8tXxU4u5F8Iduj5pEBWJEyPDPqlubaUbYw PZwbHASdjkCR6Bq5s9ScMKLvAHx1xRkwgCxtRscANuHL4txIkdDTtq05x7mEYC8lJrLL beQyjalW+7mytAMiyHTsREuIhm9x0m2sTcq72IKMhZ5cyia1vw6xPRmumN0IvnfL4/jJ RUyGn6DdcsR2wojiwsRcSGsd/RJhqf/bocIOJN2SI9FtGL9IXcmefWnObcCCZ5x/nWqq VHTg== 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:mime-version :content-disposition; bh=9tX/Z40xttowv6FIAiBrxFebJVgKU/Ic4x46Vfc+GD4=; b=ibnO57fdqgSqC+8IgsvOfQZVwaqYx02l1abUjLRXw3dt4KX7TRFOuwGrheY7hdqwrA rQ78mdevTxY73PQNfeFoc33Ul12HJutueIP6Y3+S3rppaZt6kaFwluDcX+JJoUJoUuo6 +mGRegt5vRFPJHcwSqb2zOKFX8KUXobx3P7PH88f7M15HmY6S9x2elp/o8pEZZPMHSR9 u11YCSeT4H2Ybw2izN3TuKc18RHAqYsOEsvNQkAckZtNj9M4weaE66D36UlPNWhlji3O 0sCieD4TQipQce69HFliBOAs1dckT6C23Q0Latd3knSPaJOoQo4FPIl7BaUIMV2IHab1 c3uQ== X-Gm-Message-State: AOAM533FzopzcbXcLhytCN7GR9HxQMwDJQK6X1p/T885MpbFgoJwZDXf FCcGT+PJBft/Npi6On2WB2+W3s1GRNP1FWWW X-Google-Smtp-Source: ABdhPJwJzbrDHtvOPQW4NxQHFeMNo4Ozy3CUjO3B0zjOMw7shiAbefUQCNHHZBhnKTqd/NobDfHfvQ== X-Received: by 2002:adf:eed1:: with SMTP id a17mr2524027wrp.401.1603188360106; Tue, 20 Oct 2020 03:06:00 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id f6sm2113683wru.50.2020.10.20.03.05.58 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 20 Oct 2020 03:05:59 -0700 (PDT) Date: Tue, 20 Oct 2020 11:05:57 +0100 From: Jozef Lawrynowicz To: gnu-gabi@sourceware.org Subject: [RFC] SHF_GNU_ABIND Section Flag Message-ID: <20201020100557.es5dsamudddio2kk@jozef-acer-manjaro> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="wh2rqpf7wxlicep3" Content-Disposition: inline X-Spam-Status: No, score=-10.8 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: Tue, 20 Oct 2020 10:06:11 -0000 --wh2rqpf7wxlicep3 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline 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 =========================================================== ----------------------- 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++; } --wh2rqpf7wxlicep3 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="0001-Implement-SHF_GNU_ABIND.patch" >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 --wh2rqpf7wxlicep3--