diff options
author | Sriraman Tallam <tmsriram@google.com> | 2011-09-29 23:45:57 +0000 |
---|---|---|
committer | Sriraman Tallam <tmsriram@google.com> | 2011-09-29 23:45:57 +0000 |
commit | f0558624db8e79622bb71ea5279ec6b5f8c9bc79 (patch) | |
tree | d197f7cab34bbcca71419dd08cdc05e47d661d0d /gold | |
parent | a7dac15368485853f4bd463352afb9b49517b624 (diff) | |
download | fsf-binutils-gdb-f0558624db8e79622bb71ea5279ec6b5f8c9bc79.zip fsf-binutils-gdb-f0558624db8e79622bb71ea5279ec6b5f8c9bc79.tar.gz fsf-binutils-gdb-f0558624db8e79622bb71ea5279ec6b5f8c9bc79.tar.bz2 |
2011-09-29 Sriraman Tallam <tmsriram@google.com>
* layout.h (section_order_map_): New member.
(get_section_order_map): New member function.
* output.cc (Output_section::add_input_section): Check for patterns
only when --section-ordering-file is specified.
* gold.cc (queue_middle_tasks): Delay updating order of sections till
output_sections have been formed.
* layout.cc (Layout_Layout): Initialize section_order_map_.
* plugin.cc (update_section_order): Store order in order_map. Do not
update the order.
* testsuite/Makefile.am: Add test case for plugin_final_layout.
* testsuite/Makefile.in: Regenerate.
* testsuite/plugin_section_order.c: New file.
* testsuite/plugin_final_layout.cc: New file.
* testsuite/plugin_final_layout.sh: New file.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 17 | ||||
-rw-r--r-- | gold/gold.cc | 14 | ||||
-rw-r--r-- | gold/layout.cc | 1 | ||||
-rw-r--r-- | gold/layout.h | 7 | ||||
-rw-r--r-- | gold/output.cc | 11 | ||||
-rw-r--r-- | gold/output.h | 2 | ||||
-rw-r--r-- | gold/plugin.cc | 20 | ||||
-rw-r--r-- | gold/testsuite/Makefile.am | 14 | ||||
-rw-r--r-- | gold/testsuite/Makefile.in | 19 | ||||
-rw-r--r-- | gold/testsuite/plugin_final_layout.cc | 41 | ||||
-rwxr-xr-x | gold/testsuite/plugin_final_layout.sh | 60 | ||||
-rw-r--r-- | gold/testsuite/plugin_section_order.c | 167 |
12 files changed, 355 insertions, 18 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index a00a8e4..e12a151 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,20 @@ +2011-09-29 Sriraman Tallam <tmsriram@google.com> + + * layout.h (section_order_map_): New member. + (get_section_order_map): New member function. + * output.cc (Output_section::add_input_section): Check for patterns + only when --section-ordering-file is specified. + * gold.cc (queue_middle_tasks): Delay updating order of sections till + output_sections have been formed. + * layout.cc (Layout_Layout): Initialize section_order_map_. + * plugin.cc (update_section_order): Store order in order_map. Do not + update the order. + * testsuite/Makefile.am: Add test case for plugin_final_layout. + * testsuite/Makefile.in: Regenerate. + * testsuite/plugin_section_order.c: New file. + * testsuite/plugin_final_layout.cc: New file. + * testsuite/plugin_final_layout.sh: New file. + 2011-09-29 Cary Coutant <ccoutant@google.com> * gold/incremental.cc (Sized_incremental_binary::do_process_got_plt): diff --git a/gold/gold.cc b/gold/gold.cc index 693ff79..2700bdb 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -539,6 +539,20 @@ queue_middle_tasks(const General_options& options, } } + /* If plugins have specified a section order, re-arrange input sections + according to a specified section order. If --section-ordering-file is + also specified, do not do anything here. */ + if (parameters->options().has_plugins() + && layout->is_section_ordering_specified() + && !parameters->options().section_ordering_file ()) + { + for (Layout::Section_list::const_iterator p + = layout->section_list().begin(); + p != layout->section_list().end(); + ++p) + (*p)->update_section_layout(layout->get_section_order_map()); + } + // Layout deferred objects due to plugins. if (parameters->options().has_plugins()) { diff --git a/gold/layout.cc b/gold/layout.cc index 1c32bcf..2f77e56 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -410,6 +410,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) script_output_section_data_list_(), segment_states_(NULL), relaxation_debug_check_(NULL), + section_order_map_(), input_section_position_(), input_section_glob_(), incremental_base_(NULL), diff --git a/gold/layout.h b/gold/layout.h index 05cb50f..d76fc96 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -522,6 +522,10 @@ class Layout const char* name, const elfcpp::Shdr<size, big_endian>& shdr, unsigned int reloc_shndx, unsigned int reloc_type, off_t* offset); + std::map<Section_id, unsigned int>* + get_section_order_map() + { return &this->section_order_map_; } + bool is_section_ordering_specified() { return this->section_ordering_specified_; } @@ -1322,6 +1326,9 @@ class Layout Segment_states* segment_states_; // A relaxation debug checker. We only create one when in debugging mode. Relaxation_debug_check* relaxation_debug_check_; + // Plugins specify section_ordering using this map. This is set in + // update_section_order in plugin.cc + std::map<Section_id, unsigned int> section_order_map_; // Hash a pattern to its position in the section ordering file. Unordered_map<std::string, unsigned int> input_section_position_; // Vector of glob only patterns in the section_ordering file. diff --git a/gold/output.cc b/gold/output.cc index 29d8e3d..63f0109 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -2476,7 +2476,10 @@ Output_section::add_input_section(Layout* layout, || layout->is_section_ordering_specified()) { Input_section isecn(object, shndx, input_section_size, addralign); - if (layout->is_section_ordering_specified()) + /* If section ordering is requested by specifying a ordering file, + using --section-ordering-file, match the section name with + a pattern. */ + if (parameters->options().section_ordering_file()) { unsigned int section_order_index = layout->find_section_order_index(std::string(secname)); @@ -3485,7 +3488,7 @@ Output_section::Input_section_sort_section_order_index_compare::operator()( void Output_section::update_section_layout( - const Section_layout_order& order_map) + const Section_layout_order* order_map) { for (Input_section_list::iterator p = this->input_sections_.begin(); p != this->input_sections_.end(); @@ -3499,8 +3502,8 @@ Output_section::update_section_layout( : p->relaxed_input_section()->relobj()); unsigned int shndx = p->shndx(); Section_layout_order::const_iterator it - = order_map.find(Section_id(obj, shndx)); - if (it == order_map.end()) + = order_map->find(Section_id(obj, shndx)); + if (it == order_map->end()) continue; unsigned int section_order_index = it->second; if (section_order_index != 0) diff --git a/gold/output.h b/gold/output.h index 1bec2c0..cabec5c 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2761,7 +2761,7 @@ class Output_section : public Output_data typedef std::map<Section_id, unsigned int> Section_layout_order; void - update_section_layout(const Section_layout_order& order_map); + update_section_layout(const Section_layout_order* order_map); // Update the output section flags based on input section flags. void diff --git a/gold/plugin.cc b/gold/plugin.cc index 3ccd8d0..b5880a1 100644 --- a/gold/plugin.cc +++ b/gold/plugin.cc @@ -1630,7 +1630,7 @@ get_input_section_contents(const struct ld_plugin_section section, // which they should appear in the final layout. static enum ld_plugin_status -update_section_order(const struct ld_plugin_section *section_list, +update_section_order(const struct ld_plugin_section* section_list, unsigned int num_sections) { gold_assert(parameters->options().has_plugins()); @@ -1641,8 +1641,14 @@ update_section_order(const struct ld_plugin_section *section_list, if (section_list == NULL) return LDPS_ERR; - std::map<Section_id, unsigned int> order_map; + Layout* layout = parameters->options().plugins()->layout(); + gold_assert (layout != NULL); + std::map<Section_id, unsigned int>* order_map + = layout->get_section_order_map(); + + /* Store the mapping from Section_id to section position in layout's + order_map to consult after output sections are added. */ for (unsigned int i = 0; i < num_sections; ++i) { Object* obj = parameters->options().plugins()->get_elf_object( @@ -1651,17 +1657,9 @@ update_section_order(const struct ld_plugin_section *section_list, return LDPS_BAD_HANDLE; unsigned int shndx = section_list[i].shndx; Section_id secn_id(obj, shndx); - order_map[secn_id] = i + 1; + (*order_map)[secn_id] = i + 1; } - Layout* layout = parameters->options().plugins()->layout(); - gold_assert (layout != NULL); - - for (Layout::Section_list::const_iterator p = layout->section_list().begin(); - p != layout->section_list().end(); - ++p) - (*p)->update_section_layout(order_map); - return LDPS_OK; } diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 72917f9..06e1fd2 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -1510,6 +1510,20 @@ unused.o: unused.c unused.c: @cp /dev/null $@ +check_SCRIPTS += plugin_final_layout.sh +check_DATA += plugin_final_layout.stdout +plugin_final_layout.o: plugin_final_layout.cc + $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $< +plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld + $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o +plugin_final_layout.stdout: plugin_final_layout + $(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout + +plugin_section_order.so: plugin_section_order.o + $(LINK) -Bgcctestdir/ -shared plugin_section_order.o +plugin_section_order.o: plugin_section_order.c + $(COMPILE) -O0 -c -fpic -o $@ $< + endif PLUGINS check_PROGRAMS += exclude_libs_test diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index c00f0d0..0b4cd1c 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -306,7 +306,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_3.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_4.sh \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_6.sh \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout.sh # Test that symbols known in the IR file but not in the replacement file # produce an unresolved symbol error. @@ -318,7 +319,8 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_6.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.err \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_7.syms \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_9.err +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_9.err \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_final_layout.stdout # Make a copy of two_file_test_1.o, which does not define the symbol _Z4t16av. @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@am__append_36 = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ plugin_test_1.err \ @@ -3644,6 +3646,8 @@ plugin_test_6.sh.log: plugin_test_6.sh @p='plugin_test_6.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) plugin_test_7.sh.log: plugin_test_7.sh @p='plugin_test_7.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +plugin_final_layout.sh.log: plugin_final_layout.sh + @p='plugin_final_layout.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) exclude_libs_test.sh.log: exclude_libs_test.sh @p='exclude_libs_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) discard_locals_test.sh.log: discard_locals_test.sh @@ -4756,6 +4760,17 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -c -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@unused.c: @GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ @cp /dev/null $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.o: plugin_final_layout.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fdata-sections -g -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout: plugin_final_layout.o plugin_section_order.so gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--plugin,"./plugin_section_order.so" plugin_final_layout.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_final_layout.stdout: plugin_final_layout +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(TEST_NM) -n plugin_final_layout > plugin_final_layout.stdout + +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.so: plugin_section_order.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(LINK) -Bgcctestdir/ -shared plugin_section_order.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@plugin_section_order.o: plugin_section_order.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@@PLUGINS_TRUE@ $(COMPILE) -O0 -c -fpic -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@exclude_libs_test.syms: exclude_libs_test @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< >$@ 2>/dev/null @GCC_TRUE@@NATIVE_LINKER_TRUE@libexclude_libs_test_1.a: exclude_libs_test_1.o diff --git a/gold/testsuite/plugin_final_layout.cc b/gold/testsuite/plugin_final_layout.cc new file mode 100644 index 0000000..3e264f6 --- /dev/null +++ b/gold/testsuite/plugin_final_layout.cc @@ -0,0 +1,41 @@ +// plugin_final_layout.cc -- a test case for gold + +// Copyright 2011 Free Software Foundation, Inc. +// Written by Sriraman Tallam <tmsriram@google.com>. + +// This file is part of gold. + +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3 of the License, or +// (at your option) any later version. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +// MA 02110-1301, USA. + +// The goal of this program is to verify if section ordering +// via plugins happens correctly. + +void bar () +{ +} + +void baz () +{ +} + +void foo () +{ +} + +int main () +{ + return 0; +} diff --git a/gold/testsuite/plugin_final_layout.sh b/gold/testsuite/plugin_final_layout.sh new file mode 100755 index 0000000..600f8e2 --- /dev/null +++ b/gold/testsuite/plugin_final_layout.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# plugin_final_layout.sh -- test + +# Copyright 2011 Free Software Foundation, Inc. +# Written by Sriraman Tallam <tmsriram@google.com>. + +# This file is part of gold. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. + +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, +# MA 02110-1301, USA. + +# The goal of this program is to verify if --section-ordering-file works as +# intended. File final_layout.cc is in this test. + + +set -e + +check() +{ + awk " +BEGIN { saw1 = 0; saw2 = 0; err = 0; } +/.*$2\$/ { saw1 = 1; } +/.*$3\$/ { + saw2 = 1; + if (!saw1) + { + printf \"layout of $2 and $3 is not right\\n\"; + err = 1; + exit 1; + } + } +END { + if (!saw1 && !err) + { + printf \"did not see $2\\n\"; + exit 1; + } + if (!saw2 && !err) + { + printf \"did not see $3\\n\"; + exit 1; + } + }" $1 +} + +check plugin_final_layout.stdout "_Z3foov" "_Z3barv" +check plugin_final_layout.stdout "_Z3barv" "_Z3bazv" diff --git a/gold/testsuite/plugin_section_order.c b/gold/testsuite/plugin_section_order.c new file mode 100644 index 0000000..0e2079b --- /dev/null +++ b/gold/testsuite/plugin_section_order.c @@ -0,0 +1,167 @@ +/* plugin_section_reorder.c -- Simple plugin to reorder function sections + + Copyright 2011 Free Software Foundation, Inc. + Written by Sriraman Tallam <tmsriram@google.com>. + + This file is part of gold. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, + MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include "plugin-api.h" + +static ld_plugin_get_input_section_count get_input_section_count = NULL; +static ld_plugin_get_input_section_type get_input_section_type = NULL; +static ld_plugin_get_input_section_name get_input_section_name = NULL; +static ld_plugin_get_input_section_contents get_input_section_contents = NULL; +static ld_plugin_update_section_order update_section_order = NULL; +static ld_plugin_allow_section_ordering allow_section_ordering = NULL; + +enum ld_plugin_status onload(struct ld_plugin_tv *tv); +enum ld_plugin_status claim_file_hook(const struct ld_plugin_input_file *file, + int *claimed); +enum ld_plugin_status all_symbols_read_hook(void); + +/* Plugin entry point. */ +enum ld_plugin_status +onload(struct ld_plugin_tv *tv) +{ + struct ld_plugin_tv *entry; + for (entry = tv; entry->tv_tag != LDPT_NULL; ++entry) + { + switch (entry->tv_tag) + { + case LDPT_REGISTER_CLAIM_FILE_HOOK: + assert((*entry->tv_u.tv_register_claim_file) (claim_file_hook) == LDPS_OK); + break; + case LDPT_REGISTER_ALL_SYMBOLS_READ_HOOK: + assert((*entry->tv_u.tv_register_all_symbols_read) (all_symbols_read_hook) + == LDPS_OK); + break; + case LDPT_GET_INPUT_SECTION_COUNT: + get_input_section_count = *entry->tv_u.tv_get_input_section_count; + break; + case LDPT_GET_INPUT_SECTION_TYPE: + get_input_section_type = *entry->tv_u.tv_get_input_section_type; + break; + case LDPT_GET_INPUT_SECTION_NAME: + get_input_section_name = *entry->tv_u.tv_get_input_section_name; + break; + case LDPT_GET_INPUT_SECTION_CONTENTS: + get_input_section_contents = *entry->tv_u.tv_get_input_section_contents; + break; + case LDPT_UPDATE_SECTION_ORDER: + update_section_order = *entry->tv_u.tv_update_section_order; + break; + case LDPT_ALLOW_SECTION_ORDERING: + allow_section_ordering = *entry->tv_u.tv_allow_section_ordering; + break; + default: + break; + } + } + + if (get_input_section_count == NULL + || get_input_section_type == NULL + || get_input_section_name == NULL + || get_input_section_contents == NULL + || update_section_order == NULL + || allow_section_ordering == NULL) + { + fprintf(stderr, "Some interfaces are missing\n"); + return LDPS_ERR; + } + + return LDPS_OK; +} + +inline static int is_prefix_of(const char *prefix, const char *str) +{ + return strncmp(prefix, str, strlen (prefix)) == 0; +} + +struct ld_plugin_section section_list[3]; +int num_entries = 0; + +/* This function is called by the linker for every new object it encounters. */ +enum ld_plugin_status +claim_file_hook(const struct ld_plugin_input_file *file, int *claimed) +{ + static int is_ordering_specified = 0; + struct ld_plugin_section section; + unsigned int count = 0; + unsigned int shndx; + + *claimed = 0; + if (is_ordering_specified == 0) + { + /* Inform the linker to prepare for section reordering. */ + (*allow_section_ordering)(); + is_ordering_specified = 1; + } + + (*get_input_section_count)(file->handle, &count); + + for (shndx = 0; shndx < count; ++shndx) + { + char *name = NULL; + int position = 3; + + section.handle = file->handle; + section.shndx = shndx; + (*get_input_section_name)(section, &name); + + /* Order is foo() followed by bar() followed by baz() */ + if (is_prefix_of(".text.", name)) + { + if (strstr(name, "_Z3foov") != NULL) + position = 0; + else if (strstr(name, "_Z3barv") != NULL) + position = 1; + else if (strstr(name, "_Z3bazv") != NULL) + position = 2; + else + position = 3; + } + if (position < 3) + { + section_list[position].handle = file->handle; + section_list[position].shndx = shndx; + num_entries++; + } + } + return LDPS_OK; +} + +/* This function is called by the linker after all the symbols have been read. + At this stage, it is fine to tell the linker the desired function order. */ + +enum ld_plugin_status +all_symbols_read_hook(void) +{ + if (num_entries == 3) + update_section_order(section_list, num_entries); + + return LDPS_OK; +} + |