1 /* plugin_section_reorder.c -- Simple plugin to reorder function sections
3 Copyright (C) 2011-2025 Free Software Foundation, Inc.
4 Written by Sriraman Tallam <tmsriram@google.com>.
6 This file is part of gold.
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.
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.
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. */
31 #include "plugin-api.h"
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
;
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
,
46 enum ld_plugin_status
all_symbols_read_hook(void);
48 /* Plugin entry point. */
50 onload(struct ld_plugin_tv
*tv
)
52 struct ld_plugin_tv
*entry
;
53 for (entry
= tv
; entry
->tv_tag
!= LDPT_NULL
; ++entry
)
55 switch (entry
->tv_tag
)
57 case LDPT_REGISTER_CLAIM_FILE_HOOK
:
58 assert((*entry
->tv_u
.tv_register_claim_file
) (claim_file_hook
)
61 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK
:
62 assert((*entry
->tv_u
.tv_register_all_symbols_read
)
63 (all_symbols_read_hook
)
66 case LDPT_GET_INPUT_SECTION_COUNT
:
67 get_input_section_count
= *entry
->tv_u
.tv_get_input_section_count
;
69 case LDPT_GET_INPUT_SECTION_TYPE
:
70 get_input_section_type
= *entry
->tv_u
.tv_get_input_section_type
;
72 case LDPT_GET_INPUT_SECTION_NAME
:
73 get_input_section_name
= *entry
->tv_u
.tv_get_input_section_name
;
75 case LDPT_GET_INPUT_SECTION_CONTENTS
:
76 get_input_section_contents
77 = *entry
->tv_u
.tv_get_input_section_contents
;
79 case LDPT_UPDATE_SECTION_ORDER
:
80 update_section_order
= *entry
->tv_u
.tv_update_section_order
;
82 case LDPT_ALLOW_SECTION_ORDERING
:
83 allow_section_ordering
= *entry
->tv_u
.tv_allow_section_ordering
;
85 case LDPT_ALLOW_UNIQUE_SEGMENT_FOR_SECTIONS
:
86 allow_unique_segment_for_sections
87 = *entry
->tv_u
.tv_allow_unique_segment_for_sections
;
89 case LDPT_UNIQUE_SEGMENT_FOR_SECTIONS
:
90 unique_segment_for_sections
91 = *entry
->tv_u
.tv_unique_segment_for_sections
;
98 if (get_input_section_count
== NULL
99 || get_input_section_type
== NULL
100 || get_input_section_name
== NULL
101 || get_input_section_contents
== NULL
102 || update_section_order
== NULL
103 || allow_section_ordering
== NULL
104 || allow_unique_segment_for_sections
== NULL
105 || unique_segment_for_sections
== NULL
)
107 fprintf(stderr
, "Some interfaces are missing\n");
114 inline static int is_prefix_of(const char *prefix
, const char *str
)
116 return strncmp(prefix
, str
, strlen (prefix
)) == 0;
119 struct ld_plugin_section section_list
[3];
122 /* This function is called by the linker for every new object it encounters. */
123 enum ld_plugin_status
124 claim_file_hook(const struct ld_plugin_input_file
*file
, int *claimed
)
126 static int is_ordering_specified
= 0;
127 struct ld_plugin_section section
;
128 unsigned int count
= 0;
132 if (is_ordering_specified
== 0)
134 /* Inform the linker to prepare for section reordering. */
135 (*allow_section_ordering
)();
136 /* Inform the linker to prepare to map some sections to unique
138 (*allow_unique_segment_for_sections
)();
139 is_ordering_specified
= 1;
142 (*get_input_section_count
)(file
->handle
, &count
);
144 for (shndx
= 0; shndx
< count
; ++shndx
)
149 section
.handle
= file
->handle
;
150 section
.shndx
= shndx
;
151 (*get_input_section_name
)(section
, &name
);
153 /* Order is foo() followed by bar() followed by baz() */
154 if (is_prefix_of(".text.", name
))
156 if (strstr(name
, "_Z3foov") != NULL
)
158 else if (strstr(name
, "_Z3barv") != NULL
)
160 else if (strstr(name
, "_Z3bazv") != NULL
)
167 section_list
[position
].handle
= file
->handle
;
168 section_list
[position
].shndx
= shndx
;
175 /* This function is called by the linker after all the symbols have been read.
176 At this stage, it is fine to tell the linker the desired function order. */
178 enum ld_plugin_status
179 all_symbols_read_hook(void)
181 if (num_entries
== 3)
183 update_section_order(section_list
, num_entries
);
184 unique_segment_for_sections (".text.plugin_created_unique", 0, 0x1000,
185 section_list
, num_entries
);