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