doing a relocatable link.
typename Elf_types<size>::Elf_WXword
section_flags(unsigned int shndx);
+ // Return the address of section SHNDX.
+ typename Elf_types<size>::Elf_Addr
+ section_addr(unsigned int shndx);
+
// Return the type of section SHNDX.
Elf_Word
section_type(unsigned int shndx);
return shdr.get_sh_flags();
}
+// Return the address of section SHNDX.
+
+template<int size, bool big_endian, typename File>
+typename Elf_types<size>::Elf_Addr
+Elf_file<size, big_endian, File>::section_addr(unsigned int shndx)
+{
+ File* const file = this->file_;
+
+ if (shndx >= this->shnum())
+ file->error(_("section_flags: bad shndx %u >= %u"),
+ shndx, this->shnum());
+
+ typename File::View v(file->view(this->section_header_offset(shndx),
+ This::shdr_size));
+
+ Ef_shdr shdr(v.data());
+ return shdr.get_sh_addr();
+}
+
// Return the type of section SHNDX.
template<int size, bool big_endian, typename File>
do_section_flags(unsigned int shndx)
{ return this->elf_file_.section_flags(shndx); }
+ // Return section address.
+ uint64_t
+ do_section_address(unsigned int shndx)
+ { return this->elf_file_.section_addr(shndx); }
+
// Return section type.
unsigned int
do_section_type(unsigned int shndx)
: file_()
{
this->input_argument_ =
- new Input_file_argument(name, false, "", Position_dependent_options());
+ new Input_file_argument(name, false, "", false,
+ Position_dependent_options());
bool ok = file_.open(task, name, contents, size);
gold_assert(ok);
}
const char*
Input_file::name() const
-{ return this->input_argument_->name(); }
+{
+ return this->input_argument_->name();
+}
+
+// Return whether we are only reading symbols.
+
+bool
+Input_file::just_symbols() const
+{
+ return this->input_argument_->just_symbols();
+}
// Open the file.
is_in_sysroot() const
{ return this->is_in_sysroot_; }
+ // Return whether this file is to be read only for its symbols.
+ bool
+ just_symbols() const;
+
private:
Input_file(const Input_file&);
Input_file& operator=(const Input_file&);
// If there is a SECTIONS clause, put all the input sections into
// the required order.
Output_segment* load_seg;
- if (parameters->output_is_object())
- load_seg = NULL;
- else if (this->script_options_->saw_sections_clause())
+ if (this->script_options_->saw_sections_clause())
load_seg = this->set_section_addresses_from_script(symtab);
+ else if (parameters->output_is_object())
+ load_seg = NULL;
else
load_seg = this->find_first_load_seg();
std::vector<Map_to_output>& map_sections(this->map_to_output());
map_sections.resize(shnum);
+ // If we are only linking for symbols, then there is nothing else to
+ // do here.
+ if (this->input_file()->just_symbols())
+ {
+ delete sd->section_headers;
+ sd->section_headers = NULL;
+ delete sd->section_names;
+ sd->section_names = NULL;
+ return;
+ }
+
// Whether we've seen a .note.GNU-stack section.
bool seen_gnu_stack = false;
// The flags of a .note.GNU-stack section.
release()
{ this->input_file_->file().release(); }
+ // Return whether we should just read symbols from this file.
+ bool
+ just_symbols() const
+ { return this->input_file()->just_symbols(); }
+
// Return the sized target structure associated with this object.
// This is like the target method but it returns a pointer of
// appropriate checked type.
section_flags(unsigned int shndx)
{ return this->do_section_flags(shndx); }
+ // Return the section address given a section index.
+ uint64_t
+ section_address(unsigned int shndx)
+ { return this->do_section_address(shndx); }
+
// Return the section type given a section index.
unsigned int
section_type(unsigned int shndx)
virtual uint64_t
do_section_flags(unsigned int shndx) = 0;
+ // Get section address--implemented by child class.
+ virtual uint64_t
+ do_section_address(unsigned int shndx) = 0;
+
// Get section type--implemented by child class.
virtual unsigned int
do_section_type(unsigned int shndx) = 0;
do_section_flags(unsigned int shndx)
{ return this->elf_file_.section_flags(shndx); }
+ // Return section address.
+ uint64_t
+ do_section_address(unsigned int shndx)
+ { return this->elf_file_.section_addr(shndx); }
+
// Return section type.
unsigned int
do_section_type(unsigned int shndx)
return cmdline->process_l_option(argc, argv, arg, long_option);
}
+// Handle the -R option. Historically the GNU linker made -R a
+// synonym for --just-symbols. ELF linkers have traditionally made -R
+// a synonym for -rpath. When ELF support was added to the GNU
+// linker, -R was changed to switch based on the argument: if the
+// argument is an ordinary file, we treat it as --just-symbols,
+// otherwise we treat it as -rpath. We need to be compatible with
+// this, because existing build scripts rely on it.
+
+int
+handle_r_option(int argc, char** argv, char* arg, bool long_option,
+ gold::Command_line* cmdline)
+{
+ int ret;
+ const char* val = cmdline->get_special_argument("R", argc, argv, arg,
+ long_option, &ret);
+ struct stat s;
+ if (::stat(val, &s) != 0 || S_ISDIR(s.st_mode))
+ cmdline->add_to_rpath(val);
+ else
+ cmdline->add_just_symbols_file(val);
+ return ret;
+}
+
+// Handle the --just-symbols option.
+
+int
+handle_just_symbols_option(int argc, char** argv, char* arg,
+ bool long_option, gold::Command_line* cmdline)
+{
+ int ret;
+ const char* val = cmdline->get_special_argument("just-symbols", argc, argv,
+ arg, long_option, &ret);
+ cmdline->add_just_symbols_file(val);
+ return ret;
+}
+
// Handle the special -T/--script option, which reads a linker script.
int
len += 2;
}
printf(options[j].help_output);
- len += std::strlen(options[i].help_output);
+ len += std::strlen(options[j].help_output);
comma = true;
}
else
&General_options::set_optimization_level),
GENERAL_NOARG('r', NULL, N_("Generate relocatable output"), NULL,
ONE_DASH, &General_options::set_relocatable),
- GENERAL_ARG('R', "rpath", N_("Add DIR to runtime search path"),
- N_("-R DIR, -rpath DIR"), ONE_DASH,
- &General_options::add_to_rpath),
+ // -R really means -rpath, but can mean --just-symbols for
+ // compatibility with GNU ld. -rpath is always -rpath, so we list
+ // it separately.
+ SPECIAL('R', NULL, N_("Add DIR to runtime search path"),
+ N_("-R DIR"), ONE_DASH, &handle_r_option),
+ GENERAL_ARG('\0', "rpath", NULL, N_("-rpath DIR"), ONE_DASH,
+ &General_options::add_to_rpath),
+ SPECIAL('\0', "just-symbols", N_("Read only symbol values from file"),
+ N_("-R FILE, --just-symbols FILE"), TWO_DASHES,
+ &handle_just_symbols_option),
GENERAL_ARG('\0', "rpath-link",
N_("Add DIR to link time shared library search path"),
N_("--rpath-link DIR"), TWO_DASHES,
void
Command_line::add_file(const char* name, bool is_lib)
{
- Input_file_argument file(name, is_lib, "", this->position_options_);
+ Input_file_argument file(name, is_lib, "", false, this->position_options_);
this->inputs_.add_file(file);
}
// extra_search_path: an extra directory to look for the file, prior
// to checking the normal library search path. If this is "",
// then no extra directory is added.
+ // just_symbols: whether this file only defines symbols.
// options: The position dependent options at this point in the
// command line, such as --whole-archive.
Input_file_argument()
- : name_(), is_lib_(false), extra_search_path_(""), options_()
+ : name_(), is_lib_(false), extra_search_path_(""), just_symbols_(false),
+ options_()
{ }
Input_file_argument(const char* name, bool is_lib,
const char* extra_search_path,
+ bool just_symbols,
const Position_dependent_options& options)
: name_(name), is_lib_(is_lib), extra_search_path_(extra_search_path),
- options_(options)
+ just_symbols_(just_symbols), options_(options)
{ }
const char*
: this->extra_search_path_.c_str());
}
+ // Return whether we should only read symbols from this file.
+ bool
+ just_symbols() const
+ { return this->just_symbols_; }
+
// Return whether this file may require a search using the -L
// options.
bool
std::string name_;
bool is_lib_;
std::string extra_search_path_;
+ bool just_symbols_;
Position_dependent_options options_;
};
int
process_l_option(int, char**, char*, bool);
+ // Handle a -R option when it means --rpath.
+ void
+ add_to_rpath(const char* arg)
+ { this->options_.add_to_rpath(arg); }
+
+ // Add a file for which we just read the symbols.
+ void
+ add_just_symbols_file(const char* arg)
+ {
+ this->inputs_.add_file(Input_file_argument(arg, false, "", true,
+ this->position_options_));
+ }
+
// Handle a --start-group option.
void
start_group(const char* arg);
// so we invent a fake value.
const Task* task = reinterpret_cast<const Task*>(-1);
- Input_file_argument input_argument(filename, false, "",
+ Input_file_argument input_argument(filename, false, "", false,
cmdline->position_dependent_options());
Input_file input_file(&input_argument);
if (!input_file.open(cmdline->options(), dirsearch, task))
}
Input_file_argument file(name_string.c_str(), false, extra_search_path,
- closure->position_dependent_options());
+ false, closure->position_dependent_options());
closure->inputs()->add_file(file);
}
const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+ const bool just_symbols = relobj->just_symbols();
+
const unsigned char* p = syms;
for (size_t i = 0; i < count; ++i, p += sym_size)
{
local = true;
}
+ if (just_symbols)
+ {
+ if (psym != &sym2)
+ memcpy(symbuf, p, sym_size);
+ elfcpp::Sym_write<size, big_endian> sw(symbuf);
+ sw.put_st_shndx(elfcpp::SHN_ABS);
+ if (st_shndx != elfcpp::SHN_UNDEF
+ && st_shndx < elfcpp::SHN_LORESERVE)
+ {
+ // Symbol values in object files are section relative.
+ // This is normally what we want, but since here we are
+ // converting the symbol to absolute we need to add the
+ // section address. The section address in an object
+ // file is normally zero, but people can use a linker
+ // script to change it.
+ sw.put_st_value(sym2.get_st_value()
+ + relobj->section_address(st_shndx));
+ }
+ psym = &sym2;
+ }
+
Sized_symbol<size>* res;
if (ver == NULL)
{
gold_assert(size == dynobj->target()->get_size());
gold_assert(size == parameters->get_size());
+ if (dynobj->just_symbols())
+ {
+ gold_error(_("--just-symbols does not make sense with a shared object"));
+ return;
+ }
+
if (versym != NULL && versym_size / 2 < count)
{
dynobj->error(_("too few symbol versions"));
}
unsigned int shndx;
- typename elfcpp::Elf_types<32>::Elf_Addr value = sym->value();
+ typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value();
+ typename elfcpp::Elf_types<size>::Elf_Addr dynsym_value = sym_value;
switch (sym->source())
{
case Symbol::FROM_OBJECT:
if (symobj->is_dynamic())
{
if (sym->needs_dynsym_value())
- value = target->dynsym_value(sym);
+ dynsym_value = target->dynsym_value(sym);
shndx = elfcpp::SHN_UNDEF;
}
else if (in_shndx == elfcpp::SHN_UNDEF
&secoff);
gold_assert(os != NULL);
shndx = os->out_shndx();
+
+ // In object files symbol values are section
+ // relative.
+ if (parameters->output_is_object())
+ sym_value -= os->address();
}
}
}
gold_assert(sym_index < output_count);
unsigned char* ps = psyms + (sym_index * sym_size);
this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
- sym, sym->value(), shndx, sympool, ps
+ sym, sym_value, shndx, sympool, ps
SELECT_SIZE_ENDIAN(size, big_endian));
}
gold_assert(dynsym_index < dynamic_count);
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
this->sized_write_symbol SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
- sym, value, shndx, dynpool, pd
+ sym, dynsym_value, shndx, dynpool, pd
SELECT_SIZE_ENDIAN(size, big_endian));
}
}
script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t
script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t
+check_PROGRAMS += justsyms
+justsyms_SOURCES = justsyms_1.cc
+justsyms_DEPENDENCIES = gcctestdir/ld justsyms_2r.o
+justsyms_LDFLAGS = -Bgcctestdir/ -Wl,-R,justsyms_2r.o
+justsyms_2.o: justsyms_2.cc
+ $(CXXCOMPILE) -c -o $@ $<
+justsyms_2r.o: justsyms_2.o gcctestdir/ld
+ gcctestdir/ld -o $@ -r -T $(srcdir)/justsyms.t justsyms_2.o
+
if OBJDUMP_AND_CPPFILT
check_SCRIPTS += ver_matching_test.sh
check_DATA += ver_matching_test.stdout
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test script_test_1 \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2 justsyms
@GCC_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \
@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
@GCC_FALSE@ $(am__DEPENDENCIES_1)
@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \
@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \
@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1)
+@GCC_FALSE@justsyms_DEPENDENCIES = libgoldtest.a ../libgold.a \
+@GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
+@GCC_FALSE@ $(am__DEPENDENCIES_1)
+@NATIVE_LINKER_FALSE@justsyms_DEPENDENCIES = libgoldtest.a \
+@NATIVE_LINKER_FALSE@ ../libgold.a ../../libiberty/libiberty.a \
+@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1) \
+@NATIVE_LINKER_FALSE@ $(am__DEPENDENCIES_1)
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@am__append_11 = ver_matching_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@ script_test_3.sh
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@am__append_12 = ver_matching_test.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1$(EXEEXT) \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2$(EXEEXT)
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms$(EXEEXT)
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@am__EXEEXT_8 = script_test_3$(EXEEXT)
basic_pic_test_SOURCES = basic_pic_test.c
basic_pic_test_OBJECTS = basic_pic_test.$(OBJEXT)
flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES = \
libgoldtest.a ../libgold.a ../../libiberty/libiberty.a \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
+am__justsyms_SOURCES_DIST = justsyms_1.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@am_justsyms_OBJECTS = \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms_1.$(OBJEXT)
+justsyms_OBJECTS = $(am_justsyms_OBJECTS)
+justsyms_LDADD = $(LDADD)
am_object_unittest_OBJECTS = object_unittest.$(OBJEXT)
object_unittest_OBJECTS = $(am_object_unittest_OBJECTS)
object_unittest_LDADD = $(LDADD)
$(exception_static_test_SOURCES) $(exception_test_SOURCES) \
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
flagstest_o_specialfile_and_compress_debug_sections.c \
- $(object_unittest_SOURCES) $(script_test_1_SOURCES) \
- $(script_test_2_SOURCES) script_test_3.c \
- $(tls_pic_test_SOURCES) $(tls_shared_ie_test_SOURCES) \
+ $(justsyms_SOURCES) $(object_unittest_SOURCES) \
+ $(script_test_1_SOURCES) $(script_test_2_SOURCES) \
+ script_test_3.c $(tls_pic_test_SOURCES) \
+ $(tls_shared_ie_test_SOURCES) \
$(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \
$(tls_static_pic_test_SOURCES) $(tls_static_test_SOURCES) \
$(tls_test_SOURCES) $(two_file_mixed_2_shared_test_SOURCES) \
$(am__exception_test_SOURCES_DIST) \
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
flagstest_o_specialfile_and_compress_debug_sections.c \
- $(object_unittest_SOURCES) $(am__script_test_1_SOURCES_DIST) \
+ $(am__justsyms_SOURCES_DIST) $(object_unittest_SOURCES) \
+ $(am__script_test_1_SOURCES_DIST) \
$(am__script_test_2_SOURCES_DIST) script_test_3.c \
$(am__tls_pic_test_SOURCES_DIST) \
$(am__tls_shared_ie_test_SOURCES_DIST) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_SOURCES = script_test_2.cc script_test_2a.cc script_test_2b.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_DEPENDENCIES = gcctestdir/ld script_test_2.t
@GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_2_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_2.t
+@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_SOURCES = justsyms_1.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_DEPENDENCIES = gcctestdir/ld justsyms_2r.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_LDFLAGS = -Bgcctestdir/ -Wl,-R,justsyms_2r.o
all: all-am
.SUFFIXES:
@NATIVE_LINKER_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES)
@NATIVE_LINKER_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT)
@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_LDFLAGS) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS)
+justsyms$(EXEEXT): $(justsyms_OBJECTS) $(justsyms_DEPENDENCIES)
+ @rm -f justsyms$(EXEEXT)
+ $(CXXLINK) $(justsyms_LDFLAGS) $(justsyms_OBJECTS) $(justsyms_LDADD) $(LIBS)
object_unittest$(EXEEXT): $(object_unittest_OBJECTS) $(object_unittest_DEPENDENCIES)
@rm -f object_unittest$(EXEEXT)
$(CXXLINK) $(object_unittest_LDFLAGS) $(object_unittest_OBJECTS) $(object_unittest_LDADD) $(LIBS)
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_compress_debug_sections.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/object_unittest.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/script_test_2.Po@am__quote@
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $<
@GCC_TRUE@@NATIVE_LINKER_TRUE@ver_test_4.o: ver_test_4.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2.o: justsyms_2.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2r.o: justsyms_2.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir/ld -o $@ -r -T $(srcdir)/justsyms.t justsyms_2.o
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@ver_matching_def.so: ver_matching_def.cc gcctestdir/ld
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@ $(CXXLINK) -O0 -Bgcctestdir/ -shared $(srcdir)/ver_matching_def.cc -Wl,--version-script=$(srcdir)/version_script.map
@GCC_TRUE@@NATIVE_LINKER_TRUE@@OBJDUMP_AND_CPPFILT_TRUE@ver_matching_test.stdout: ver_matching_def.so
--- /dev/null
+/* justsyms.t -- test --just-symbols for gold.
+
+ Copyright 2008 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor <iant@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. */
+
+SECTIONS
+{
+ /* This script is only used for a .o file. */
+ . = 0x10000;
+ .gold_test : { *(.gold_test) }
+ .text : { *(.text) }
+ .data : { *(.data) }
+ .bss : { *(.bss) }
+}
--- /dev/null
+// justsyms_1.cc -- test --just-symbols for gold
+
+// Copyright 2008 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@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 Linux kernel builds an object file using a linker script, and
+// then links against that object file using the -R option. This is a
+// test for that usage.
+
+#include <cassert>
+#include <csignal>
+#include <cstddef>
+#include <cstdlib>
+#include <stdint.h>
+
+extern char justsyms_string[];
+
+// We expect to get a SIGSEGV.
+static void
+handle_sigsegv(int)
+{
+ exit(0);
+}
+
+int
+main(int, char**)
+{
+ // The linker script should arrange for this symbol to be exactly at
+ // address 0x10000.
+ assert(reinterpret_cast<uintptr_t>(justsyms_string) == 0x10000);
+
+ // However, since the file was linked with --just-symbols, we should
+ // not be able to actually access the symbol.
+ signal(SIGSEGV, handle_sigsegv);
+ char c = justsyms_string[0];
+ exit(c == '\0' ? 1 : c);
+}
--- /dev/null
+// justsyms_2.cc -- test --just-symbols for gold
+
+// Copyright 2008 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@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.
+
+// This test goes with justsyms_1.cc. We compile this file, then
+// apply a linker script with -r to set the section addresses.
+
+char justsyms_string[] __attribute__ ((section(".gold_test"))) =
+ "justsyms string";