(root)/
binutils-2.41/
gold/
testsuite/
plugin_new_section_layout.c
       1  /* plugin_new_section_layout.c -- Simple plugin to reorder function sections in
       2     plugin-generated objects
       3  
       4     Copyright (C) 2017-2023 Free Software Foundation, Inc.
       5     Written by Stephen Crane <sjc@immunant.com>.
       6  
       7     This file is part of gold.
       8  
       9     This program is free software; you can redistribute it and/or modify
      10     it under the terms of the GNU General Public License as published by
      11     the Free Software Foundation; either version 3 of the License, or
      12     (at your option) any later version.
      13  
      14     This program is distributed in the hope that it will be useful,
      15     but WITHOUT ANY WARRANTY; without even the implied warranty of
      16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17     GNU General Public License for more details.
      18  
      19     You should have received a copy of the GNU General Public License
      20     along with this program; if not, write to the Free Software
      21     Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
      22     MA 02110-1301, USA.  */
      23  
      24  /* This plugin tests the new_input API of the linker plugin interface that
      25   * allows plugins to modify section layout and assign sections to segments for
      26   * sections in plugin-generated object files. It assumes that another plugin is
      27   * also in use which will add new files. In practice a plugin is likely to
      28   * generate new input files itself in all_symbols_read and want to
      29   * reorder/assign sections for these files in the new_input_hook callback. */
      30  
      31  #ifdef HAVE_CONFIG_H
      32  #include "config.h"
      33  #endif
      34  
      35  #include <stdio.h>
      36  #include <stdlib.h>
      37  #include <string.h>
      38  #include <assert.h>
      39  #include "plugin-api.h"
      40  #include "elf/common.h"
      41  
      42  static ld_plugin_get_input_section_count get_input_section_count = NULL;
      43  static ld_plugin_get_input_section_type get_input_section_type = NULL;
      44  static ld_plugin_get_input_section_name get_input_section_name = NULL;
      45  static ld_plugin_update_section_order update_section_order = NULL;
      46  static ld_plugin_allow_section_ordering allow_section_ordering = NULL;
      47  static ld_plugin_allow_unique_segment_for_sections 
      48      allow_unique_segment_for_sections = NULL;
      49  static ld_plugin_unique_segment_for_sections unique_segment_for_sections = NULL;
      50  
      51  enum ld_plugin_status onload(struct ld_plugin_tv *tv);
      52  enum ld_plugin_status new_input_hook(const struct ld_plugin_input_file *file);
      53  
      54  /* Plugin entry point.  */
      55  enum ld_plugin_status
      56  onload(struct ld_plugin_tv *tv)
      57  {
      58    struct ld_plugin_tv *entry;
      59    for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry)
      60      {
      61        switch (entry->tv_tag)
      62          {
      63          case LDPT_GET_INPUT_SECTION_COUNT:
      64            get_input_section_count = *entry->tv_u.tv_get_input_section_count;
      65            break;
      66          case LDPT_GET_INPUT_SECTION_TYPE:
      67            get_input_section_type = *entry->tv_u.tv_get_input_section_type;
      68            break;
      69          case LDPT_GET_INPUT_SECTION_NAME:
      70            get_input_section_name = *entry->tv_u.tv_get_input_section_name;
      71            break;
      72  	case LDPT_UPDATE_SECTION_ORDER:
      73  	  update_section_order = *entry->tv_u.tv_update_section_order;
      74  	  break;
      75  	case LDPT_ALLOW_SECTION_ORDERING:
      76  	  allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
      77  	  break;
      78  	case LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS:
      79  	  allow_unique_segment_for_sections
      80  	      = *entry->tv_u.tv_allow_unique_segment_for_sections;
      81  	  break;
      82  	case LDPT_UNIQUE_SEGMENT_FOR_SECTIONS:
      83  	  unique_segment_for_sections
      84  	      = *entry->tv_u.tv_unique_segment_for_sections;
      85  	  break;
      86          case LDPT_REGISTER_NEW_INPUT_HOOK:
      87            assert((*entry->tv_u.tv_register_new_input) (new_input_hook)
      88  		 == LDPS_OK);
      89            break;
      90          default:
      91            break;
      92          }
      93      }
      94  
      95    if (get_input_section_count == NULL
      96        || get_input_section_type == NULL
      97        || get_input_section_name == NULL
      98        || update_section_order == NULL
      99        || allow_section_ordering == NULL
     100        || allow_unique_segment_for_sections == NULL
     101        || unique_segment_for_sections == NULL)
     102      {
     103        fprintf(stderr, "Some interfaces are missing\n");
     104        return LDPS_ERR;
     105      }
     106  
     107    /* Inform the linker to prepare for section reordering.  */
     108    (*allow_section_ordering)();
     109    /* Inform the linker to prepare to map some sections to unique
     110       segments.  */
     111    (*allow_unique_segment_for_sections)(); 
     112  
     113    return LDPS_OK;
     114  }
     115  
     116  inline static int is_prefix_of(const char *prefix, const char *str)
     117  {
     118    return strncmp(prefix, str, strlen (prefix)) == 0;
     119  }
     120  
     121  /* This function is called by the linker when new files are added by a plugin.
     122     We can now tell the linker the desired function order since we have a file
     123     handle for the newly added file.  */
     124  
     125  enum ld_plugin_status
     126  new_input_hook(const struct ld_plugin_input_file *file)
     127  {
     128    struct ld_plugin_section section_list[3];
     129    int num_entries = 0;
     130    unsigned int count;
     131  
     132    if (get_input_section_count(file->handle, &count) != LDPS_OK)
     133      return LDPS_ERR;
     134  
     135    unsigned int i;
     136    for (i = 0; i < count; ++i)
     137    {
     138      struct ld_plugin_section section;
     139      unsigned int type = 0;
     140      char *name = NULL;
     141      int position = 3;
     142  
     143      section.handle = file->handle;
     144      section.shndx = i;
     145  
     146      if (get_input_section_type(section, &type) != LDPS_OK)
     147        return LDPS_ERR;
     148      if (type != SHT_PROGBITS)
     149        continue;
     150  
     151      if (get_input_section_name(section, &name))
     152        return LDPS_ERR;
     153  
     154      /* As in plugin_section_order.c, order is foo() followed by bar()
     155         followed by baz() */
     156      if (is_prefix_of(".text.", name))
     157      {
     158        if (strstr(name, "_Z3foov") != NULL)
     159          position = 0;
     160        else if (strstr(name, "_Z3barv") != NULL)
     161          position = 1;
     162        else if (strstr(name, "_Z3bazv") != NULL)
     163          position = 2;
     164        else
     165          position = 3;
     166      }
     167      if (position < 3)
     168      {
     169        section_list[position] = section;
     170        num_entries++;
     171      }
     172    }
     173  
     174    if (num_entries != 3)
     175      return LDPS_ERR;
     176  
     177    update_section_order(section_list, num_entries);
     178    unique_segment_for_sections (".text.plugin_created_unique", 0, 0x1000,
     179                                 section_list, num_entries);
     180  
     181    return LDPS_OK;
     182  }