1 /* plugin_new_section_layout.c -- Simple plugin to reorder function sections in
2 plugin-generated objects
4 Copyright (C) 2017-2025 Free Software Foundation, Inc.
5 Written by Stephen Crane <sjc@immunant.com>.
7 This file is part of gold.
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.
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.
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. */
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. */
39 #include "plugin-api.h"
40 #include "elf/common.h"
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
;
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
);
54 /* Plugin entry point. */
56 onload(struct ld_plugin_tv
*tv
)
58 struct ld_plugin_tv
*entry
;
59 for (entry
= tv
; entry
->tv_tag
!= LDPT_NULL
; ++entry
)
61 switch (entry
->tv_tag
)
63 case LDPT_GET_INPUT_SECTION_COUNT
:
64 get_input_section_count
= *entry
->tv_u
.tv_get_input_section_count
;
66 case LDPT_GET_INPUT_SECTION_TYPE
:
67 get_input_section_type
= *entry
->tv_u
.tv_get_input_section_type
;
69 case LDPT_GET_INPUT_SECTION_NAME
:
70 get_input_section_name
= *entry
->tv_u
.tv_get_input_section_name
;
72 case LDPT_UPDATE_SECTION_ORDER
:
73 update_section_order
= *entry
->tv_u
.tv_update_section_order
;
75 case LDPT_ALLOW_SECTION_ORDERING
:
76 allow_section_ordering
= *entry
->tv_u
.tv_allow_section_ordering
;
78 case LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS
:
79 allow_unique_segment_for_sections
80 = *entry
->tv_u
.tv_allow_unique_segment_for_sections
;
82 case LDPT_UNIQUE_SEGMENT_FOR_SECTIONS
:
83 unique_segment_for_sections
84 = *entry
->tv_u
.tv_unique_segment_for_sections
;
86 case LDPT_REGISTER_NEW_INPUT_HOOK
:
87 assert((*entry
->tv_u
.tv_register_new_input
) (new_input_hook
)
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
)
103 fprintf(stderr
, "Some interfaces are missing\n");
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
111 (*allow_unique_segment_for_sections
)();
116 inline static int is_prefix_of(const char *prefix
, const char *str
)
118 return strncmp(prefix
, str
, strlen (prefix
)) == 0;
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. */
125 enum ld_plugin_status
126 new_input_hook(const struct ld_plugin_input_file
*file
)
128 struct ld_plugin_section section_list
[3];
132 if (get_input_section_count(file
->handle
, &count
) != LDPS_OK
)
136 for (i
= 0; i
< count
; ++i
)
138 struct ld_plugin_section section
;
139 unsigned int type
= 0;
143 section
.handle
= file
->handle
;
146 if (get_input_section_type(section
, &type
) != LDPS_OK
)
148 if (type
!= SHT_PROGBITS
)
151 if (get_input_section_name(section
, &name
))
154 /* As in plugin_section_order.c, order is foo() followed by bar()
156 if (is_prefix_of(".text.", name
))
158 if (strstr(name
, "_Z3foov") != NULL
)
160 else if (strstr(name
, "_Z3barv") != NULL
)
162 else if (strstr(name
, "_Z3bazv") != NULL
)
169 section_list
[position
] = section
;
174 if (num_entries
!= 3)
177 update_section_order(section_list
, num_entries
);
178 unique_segment_for_sections (".text.plugin_created_unique", 0, 0x1000,
179 section_list
, num_entries
);