OSDN Git Service

Use datarootdir for locales.
[pf3gnuchains/pf3gnuchains4x.git] / gold / testsuite / plugin_section_order.c
1 /* plugin_section_reorder.c -- Simple plugin to reorder function sections
2
3    Copyright 2011 Free Software Foundation, Inc.
4    Written by Sriraman Tallam <tmsriram@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
40 enum ld_plugin_status onload(struct ld_plugin_tv *tv);
41 enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file,
42                                       int *claimed);
43 enum ld_plugin_status all_symbols_read_hook(void);
44
45 /* Plugin entry point.  */
46 enum ld_plugin_status
47 onload(struct ld_plugin_tv *tv)
48 {
49   struct ld_plugin_tv *entry;
50   for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry)
51     {
52       switch (entry->tv_tag)
53         {
54         case LDPT_REGISTER_CLAIM_FILE_HOOK:
55           assert((*entry->tv_u.tv_register_claim_file) (claim_file_hook) == LDPS_OK);
56           break;
57         case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK:
58           assert((*entry->tv_u.tv_register_all_symbols_read) (all_symbols_read_hook)
59                   == LDPS_OK);
60           break;
61         case LDPT_GET_INPUT_SECTION_COUNT:
62           get_input_section_count = *entry->tv_u.tv_get_input_section_count;
63           break;
64         case LDPT_GET_INPUT_SECTION_TYPE:
65           get_input_section_type = *entry->tv_u.tv_get_input_section_type;
66           break;
67         case LDPT_GET_INPUT_SECTION_NAME:
68           get_input_section_name = *entry->tv_u.tv_get_input_section_name;
69           break;
70         case LDPT_GET_INPUT_SECTION_CONTENTS:
71           get_input_section_contents = *entry->tv_u.tv_get_input_section_contents;
72           break;
73         case LDPT_UPDATE_SECTION_ORDER:
74           update_section_order = *entry->tv_u.tv_update_section_order;
75           break;
76         case LDPT_ALLOW_SECTION_ORDERING:
77           allow_section_ordering = *entry->tv_u.tv_allow_section_ordering;
78           break;
79         default:
80           break;
81         }
82     }
83
84   if (get_input_section_count == NULL
85       || get_input_section_type == NULL
86       || get_input_section_name == NULL
87       || get_input_section_contents == NULL
88       || update_section_order == NULL
89       || allow_section_ordering == NULL)
90     {
91       fprintf(stderr, "Some interfaces are missing\n");
92       return LDPS_ERR;
93     }
94
95   return LDPS_OK;
96 }
97
98 inline static int is_prefix_of(const char *prefix, const char *str)
99 {
100   return strncmp(prefix, str, strlen (prefix)) == 0;
101 }
102
103 struct ld_plugin_section section_list[3];
104 int num_entries = 0;
105
106 /* This function is called by the linker for every new object it encounters.  */
107 enum ld_plugin_status
108 claim_file_hook(const struct ld_plugin_input_file *file, int *claimed)
109 {
110   static int is_ordering_specified = 0;
111   struct ld_plugin_section section;
112   unsigned int count = 0;
113   unsigned int shndx;
114
115   *claimed = 0;
116   if (is_ordering_specified == 0)
117     {
118       /* Inform the linker to prepare for section reordering.  */
119       (*allow_section_ordering)();
120       is_ordering_specified = 1;
121     }
122
123   (*get_input_section_count)(file->handle, &count);
124
125   for (shndx = 0; shndx < count; ++shndx)
126     {
127       char *name = NULL;
128       int position = 3;
129
130       section.handle = file->handle;
131       section.shndx = shndx;
132       (*get_input_section_name)(section, &name);
133
134       /* Order is foo() followed by bar() followed by baz()  */
135       if (is_prefix_of(".text.", name))
136         {
137           if (strstr(name, "_Z3foov") != NULL)
138             position = 0;
139           else if (strstr(name, "_Z3barv") != NULL)
140             position = 1;
141           else if (strstr(name, "_Z3bazv") != NULL)
142             position = 2;
143           else
144             position = 3;
145         }
146       if (position < 3)
147         {
148           section_list[position].handle = file->handle;
149           section_list[position].shndx = shndx;
150           num_entries++;
151         }
152     }
153   return LDPS_OK;
154 }
155
156 /* This function is called by the linker after all the symbols have been read.
157    At this stage, it is fine to tell the linker the desired function order.  */
158
159 enum ld_plugin_status
160 all_symbols_read_hook(void)
161 {
162   if (num_entries == 3)
163     update_section_order(section_list, num_entries);
164
165   return LDPS_OK;
166 }
167