]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gold/testsuite/plugin_new_section_layout.c
Update year range in copyright notice of binutils files
[thirdparty/binutils-gdb.git] / gold / testsuite / plugin_new_section_layout.c
CommitLineData
c4e64843
SC
1/* plugin_new_section_layout.c -- Simple plugin to reorder function sections in
2 plugin-generated objects
3
250d07de 4 Copyright (C) 2017-2021 Free Software Foundation, Inc.
c4e64843
SC
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)
6831670d 147 return LDPS_ERR;
c4e64843
SC
148 if (type != SHT_PROGBITS)
149 continue;
150
151 if (get_input_section_name(section, &name))
6831670d 152 return LDPS_ERR;
c4e64843
SC
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)
6831670d 175 return LDPS_ERR;
c4e64843
SC
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}