diff options
author | Ian Lance Taylor <iant@google.com> | 2008-02-07 01:51:25 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2008-02-07 01:51:25 +0000 |
commit | 88dd47ac00ee5a932bca9abbd2245c429dfd8f5b (patch) | |
tree | 494b3493adc0f1449c5a33f48002692a9e74ab17 /gold/symtab.cc | |
parent | 2e444beaa07a2428b6409225840ce12d437d7805 (diff) | |
download | gdb-88dd47ac00ee5a932bca9abbd2245c429dfd8f5b.zip gdb-88dd47ac00ee5a932bca9abbd2245c429dfd8f5b.tar.gz gdb-88dd47ac00ee5a932bca9abbd2245c429dfd8f5b.tar.bz2 |
Implement --just-symbols, including -R FILE. Fix symbol values when
doing a relocatable link.
Diffstat (limited to 'gold/symtab.cc')
-rw-r--r-- | gold/symtab.cc | 43 |
1 files changed, 39 insertions, 4 deletions
diff --git a/gold/symtab.cc b/gold/symtab.cc index c7f6816..85761fd 100644 --- a/gold/symtab.cc +++ b/gold/symtab.cc @@ -634,6 +634,8 @@ Symbol_table::add_from_relobj( 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) { @@ -701,6 +703,27 @@ Symbol_table::add_from_relobj( 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) { @@ -744,6 +767,12 @@ Symbol_table::add_from_dynobj( 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")); @@ -1833,7 +1862,8 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, } 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: @@ -1854,7 +1884,7 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, 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 @@ -1868,6 +1898,11 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, &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(); } } } @@ -1895,7 +1930,7 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, 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)); } @@ -1905,7 +1940,7 @@ Symbol_table::sized_write_globals(const Input_objects* input_objects, 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)); } } |