1 // plugin_section_alignment.cc -- plugins to test ordering with {size,alignment}
3 // Copyright (C) 2016-2019 Free Software Foundation, Inc.
4 // Written by Than McIntosh <thanm@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.
37 #include "plugin-api.h"
39 static ld_plugin_get_input_section_count get_input_section_count
= NULL
;
40 static ld_plugin_get_input_section_alignment get_input_section_alignment
= NULL
;
41 static ld_plugin_get_input_section_size get_input_section_size
= NULL
;
42 static ld_plugin_get_input_section_name get_input_section_name
= NULL
;
43 static ld_plugin_update_section_order update_section_order
= NULL
;
44 static ld_plugin_allow_section_ordering allow_section_ordering
= NULL
;
47 enum ld_plugin_status
onload(struct ld_plugin_tv
*tv
);
48 enum ld_plugin_status
claim_file_hook(const struct ld_plugin_input_file
*file
,
50 enum ld_plugin_status
all_symbols_read_hook(void);
53 typedef enum { FL_BSS
, FL_DATA
, FL_RODATA
, FL_UNKNOWN
} sec_flavor
;
55 inline static int is_prefix_of(const char *prefix
, const char *str
)
57 return strncmp(prefix
, str
, strlen(prefix
)) == 0;
60 inline static sec_flavor
flavor_from_name(const char *secname
)
62 if (is_prefix_of(".data.v", secname
)) {
64 } else if (is_prefix_of(".bss.v", secname
)) {
66 } else if (is_prefix_of(".rodata.v", secname
)) {
74 ld_plugin_section plugin_section
;
80 static bool SectionInfoLt(const SectionInfo
&i1
,
81 const SectionInfo
&i2
)
83 if (i1
.flavor
!= i2
.flavor
) {
84 return ((unsigned) i1
.flavor
) < ((unsigned) i2
.flavor
);
88 // Sort data items by increasing alignment then increasing size
89 if (i1
.align
!= i2
.align
) {
90 return ((unsigned) i1
.align
) < ((unsigned) i2
.align
);
92 if (i1
.size
!= i2
.size
) {
93 return ((unsigned) i1
.size
) < ((unsigned) i2
.size
);
97 // Sort bss items by decreasing alignment then decreasing size
98 if (i1
.align
!= i2
.align
) {
99 return ((unsigned) i2
.align
) < ((unsigned) i1
.align
);
101 if (i1
.size
!= i2
.size
) {
102 return ((unsigned) i2
.size
) < ((unsigned) i1
.size
);
106 // Sort rodata items by decreasing alignment then increasing size
107 if (i1
.align
!= i2
.align
) {
108 return ((unsigned) i2
.align
) < ((unsigned) i1
.align
);
110 if (i1
.size
!= i2
.size
) {
111 return ((unsigned) i1
.size
) < ((unsigned) i2
.size
);
117 // Break ties by name
118 return i1
.name
.compare(i2
.name
) < 0;
122 typedef std::vector
<SectionInfo
> section_info_vector
;
123 section_info_vector raw_sections
;
125 // Set to 1 for debugging output
130 // Plugin entry point.
131 enum ld_plugin_status
onload(struct ld_plugin_tv
*tv
)
133 struct ld_plugin_tv
*entry
;
134 for (entry
= tv
; entry
->tv_tag
!= LDPT_NULL
; ++entry
)
136 switch (entry
->tv_tag
)
139 if (!strcmp(entry
->tv_u
.tv_string
,"-trace")) {
140 fprintf(stderr
, "enabling tracing\n");
143 fprintf(stderr
, "unknown plugin option %s", entry
->tv_u
.tv_string
);
146 case LDPT_REGISTER_CLAIM_FILE_HOOK
:
147 assert((*entry
->tv_u
.tv_register_claim_file
)(claim_file_hook
) ==
150 case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK
:
151 assert((*entry
->tv_u
.tv_register_all_symbols_read
)(
152 all_symbols_read_hook
) == LDPS_OK
);
154 case LDPT_GET_INPUT_SECTION_COUNT
:
155 get_input_section_count
= *entry
->tv_u
.tv_get_input_section_count
;
157 case LDPT_GET_INPUT_SECTION_NAME
:
158 get_input_section_name
= *entry
->tv_u
.tv_get_input_section_name
;
160 case LDPT_GET_INPUT_SECTION_ALIGNMENT
:
161 get_input_section_alignment
=
162 *entry
->tv_u
.tv_get_input_section_alignment
;
164 case LDPT_GET_INPUT_SECTION_SIZE
:
165 get_input_section_size
= *entry
->tv_u
.tv_get_input_section_size
;
167 case LDPT_UPDATE_SECTION_ORDER
:
168 update_section_order
= *entry
->tv_u
.tv_update_section_order
;
170 case LDPT_ALLOW_SECTION_ORDERING
:
171 allow_section_ordering
= *entry
->tv_u
.tv_allow_section_ordering
;
178 if (get_input_section_count
== NULL
|| get_input_section_alignment
== NULL
||
179 get_input_section_size
== NULL
|| get_input_section_name
== NULL
||
180 update_section_order
== NULL
|| allow_section_ordering
== NULL
) {
181 fprintf(stderr
, "Some interfaces are missing\n");
188 // This function is called by the linker for every new object it encounters.
189 enum ld_plugin_status
claim_file_hook(const struct ld_plugin_input_file
*file
,
192 static bool is_ordering_specified
= false;
193 struct ld_plugin_section section
;
198 if (!is_ordering_specified
) {
199 // Inform the linker to prepare for section reordering.
200 (*allow_section_ordering
)();
201 is_ordering_specified
= true;
204 (*get_input_section_count
)(file
->handle
, &count
);
206 for (shndx
= 0; shndx
< count
; ++shndx
) {
209 section
.handle
= file
->handle
;
210 section
.shndx
= shndx
;
211 (*get_input_section_name
)(section
, &name
);
212 if (is_prefix_of(".data.v", name
) ||
213 is_prefix_of(".bss.v", name
) ||
214 is_prefix_of(".rodata.v", name
)) {
216 si
.plugin_section
.handle
= file
->handle
;
217 si
.plugin_section
.shndx
= shndx
;
218 (*get_input_section_size
)(section
, &si
.size
);
219 (*get_input_section_alignment
)(section
, &si
.align
);
221 si
.flavor
= flavor_from_name(name
);
222 raw_sections
.push_back(si
);
229 // This function is called by the linker after all the symbols have been read.
230 // At this stage, it is fine to tell the linker the desired function order.
232 enum ld_plugin_status
all_symbols_read_hook(void)
234 // We expect to see a total of twelve sections -- if this is not the case
235 // then something went wrong somewhere along the way.
236 if (raw_sections
.size() != 12) {
237 fprintf(stderr
, "Expected 12 sections, found %u sections",
238 (unsigned) raw_sections
.size());
242 std::sort(raw_sections
.begin(), raw_sections
.end(),
243 SectionInfo::SectionInfoLt
);
245 struct ld_plugin_section section_list
[12];
246 for (unsigned ii
= 0; ii
< 12; ++ii
) {
247 section_list
[ii
] = raw_sections
[ii
].plugin_section
;
251 fprintf(stderr
, "Specified section order is:\n");
252 for (section_info_vector::iterator it
= raw_sections
.begin();
253 it
!= raw_sections
.end();
255 const SectionInfo
&si
= (*it
);
256 fprintf(stderr
, "Idx=%u Name=%s Align=%u Size=%u\n",
257 si
.plugin_section
.shndx
, si
.name
.c_str(), si
.align
,
262 update_section_order(section_list
, 12);