plugin_new_section_layout.c revision 1.1.1.1
1/* plugin_new_section_layout.c -- Simple plugin to reorder function sections in 2 plugin-generated objects 3 4 Copyright (C) 2017-2020 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 42static ld_plugin_get_input_section_count get_input_section_count = NULL; 43static ld_plugin_get_input_section_type get_input_section_type = NULL; 44static ld_plugin_get_input_section_name get_input_section_name = NULL; 45static ld_plugin_update_section_order update_section_order = NULL; 46static ld_plugin_allow_section_ordering allow_section_ordering = NULL; 47static ld_plugin_allow_unique_segment_for_sections 48 allow_unique_segment_for_sections = NULL; 49static ld_plugin_unique_segment_for_sections unique_segment_for_sections = NULL; 50 51enum ld_plugin_status onload(struct ld_plugin_tv *tv); 52enum ld_plugin_status new_input_hook(const struct ld_plugin_input_file *file); 53 54/* Plugin entry point. */ 55enum ld_plugin_status 56onload(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 116inline 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 125enum ld_plugin_status 126new_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} 183