mirror of
https://github.com/darlinghq/darling-gdb.git
synced 2024-11-30 23:40:24 +00:00
* target.h (Target::gc_mark_symbol, do_gc_mark_symbol): New functions.
(Sized_target::gc_add_reference, do_gc_add_reference): New functions. * gc.h (gc_process_relocs): Call target gc_add_reference. * gold.cc (queue_middle_tasks): Use gc_mark_symbol on start sym. * symtab.cc (Symbol_table::gc_mark_undef_symbols): Use gc_mark_symbol. (Symbol_table::gc_mark_symbol): Call target gc_mark_symbol. Remove unnecessary cast. * powerpc.cc (Powerpc_relobj::get_opd_ent): Rearrange parameters to cater for when we don't need code offset. Update use. (Powerpc_relobj::access_from_map_, opd_valid_): New vars. (Powerpc_relobj::access_from_map, add_reference, opd_valid, set_opd_valid): New functions. (Target_powerpc::do_gc_add_reference): New function. (Target_powerpc::gc_process_relocs): Call gc()->add_reference on stashed refs. (Target_powerpc::do_gc_mark_symbol): New function.
This commit is contained in:
parent
b7099d964f
commit
e81fea4d17
@ -1,3 +1,22 @@
|
||||
2012-09-09 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* target.h (Target::gc_mark_symbol, do_gc_mark_symbol): New functions.
|
||||
(Sized_target::gc_add_reference, do_gc_add_reference): New functions.
|
||||
* gc.h (gc_process_relocs): Call target gc_add_reference.
|
||||
* gold.cc (queue_middle_tasks): Use gc_mark_symbol on start sym.
|
||||
* symtab.cc (Symbol_table::gc_mark_undef_symbols): Use gc_mark_symbol.
|
||||
(Symbol_table::gc_mark_symbol): Call target gc_mark_symbol. Remove
|
||||
unnecessary cast.
|
||||
* powerpc.cc (Powerpc_relobj::get_opd_ent): Rearrange parameters
|
||||
to cater for when we don't need code offset. Update use.
|
||||
(Powerpc_relobj::access_from_map_, opd_valid_): New vars.
|
||||
(Powerpc_relobj::access_from_map, add_reference, opd_valid,
|
||||
set_opd_valid): New functions.
|
||||
(Target_powerpc::do_gc_add_reference): New function.
|
||||
(Target_powerpc::gc_process_relocs): Call gc()->add_reference on
|
||||
stashed refs.
|
||||
(Target_powerpc::do_gc_mark_symbol): New function.
|
||||
|
||||
2012-09-06 Cary Coutant <ccoutant@google.com>
|
||||
|
||||
* dwarf_reader.cc (Dwarf_die::read_attributes): Add
|
||||
|
13
gold/gc.h
13
gold/gc.h
@ -187,8 +187,6 @@ gc_process_relocs(
|
||||
size_t local_count,
|
||||
const unsigned char* plocal_syms)
|
||||
{
|
||||
Object* dst_obj;
|
||||
unsigned int dst_indx;
|
||||
Scan scan;
|
||||
|
||||
typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
|
||||
@ -235,6 +233,9 @@ gc_process_relocs(
|
||||
unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
|
||||
typename elfcpp::Elf_types<size>::Elf_Swxword addend =
|
||||
Reloc_types<sh_type, size, big_endian>::get_reloc_addend_noerror(&reloc);
|
||||
Object* dst_obj;
|
||||
unsigned int dst_indx;
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr dst_off;
|
||||
|
||||
if (r_sym < local_count)
|
||||
{
|
||||
@ -246,6 +247,8 @@ gc_process_relocs(
|
||||
shndx = src_obj->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
|
||||
dst_obj = src_obj;
|
||||
dst_indx = shndx;
|
||||
dst_off = lsym.get_st_value();
|
||||
|
||||
if (is_icf_tracked)
|
||||
{
|
||||
if (is_ordinary)
|
||||
@ -288,11 +291,13 @@ gc_process_relocs(
|
||||
|
||||
dst_obj = NULL;
|
||||
dst_indx = 0;
|
||||
dst_off = 0;
|
||||
bool is_ordinary = false;
|
||||
if (gsym->source() == Symbol::FROM_OBJECT)
|
||||
{
|
||||
dst_obj = gsym->object();
|
||||
dst_indx = gsym->shndx(&is_ordinary);
|
||||
dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value();
|
||||
}
|
||||
|
||||
// When doing safe folding, check to see if this relocation is that
|
||||
@ -348,6 +353,10 @@ gc_process_relocs(
|
||||
if (parameters->options().gc_sections())
|
||||
{
|
||||
symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
|
||||
dst_off += addend;
|
||||
parameters->sized_target<size, big_endian>()
|
||||
->gc_add_reference(symtab, src_obj, src_indx,
|
||||
dst_obj, dst_indx, dst_off);
|
||||
if (cident_section_name != NULL)
|
||||
{
|
||||
Garbage_collection::Cident_section_map::iterator ele =
|
||||
|
10
gold/gold.cc
10
gold/gold.cc
@ -504,15 +504,7 @@ queue_middle_tasks(const General_options& options,
|
||||
// Find the start symbol if any.
|
||||
Symbol* start_sym = symtab->lookup(parameters->entry());
|
||||
if (start_sym != NULL)
|
||||
{
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = start_sym->shndx(&is_ordinary);
|
||||
if (is_ordinary)
|
||||
{
|
||||
symtab->gc()->worklist().push(
|
||||
Section_id(start_sym->object(), shndx));
|
||||
}
|
||||
}
|
||||
symtab->gc_mark_symbol(start_sym);
|
||||
// Symbols named with -u should not be considered garbage.
|
||||
symtab->gc_mark_undef_symbols(layout);
|
||||
gold_assert(symtab->gc() != NULL);
|
||||
|
153
gold/powerpc.cc
153
gold/powerpc.cc
@ -59,11 +59,14 @@ class Powerpc_relobj : public Sized_relobj_file<size, big_endian>
|
||||
public:
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
|
||||
typedef typename elfcpp::Elf_types<size>::Elf_Off Offset;
|
||||
typedef Unordered_set<Section_id, Section_id_hash> Section_refs;
|
||||
typedef Unordered_map<Address, Section_refs> Access_from;
|
||||
|
||||
Powerpc_relobj(const std::string& name, Input_file* input_file, off_t offset,
|
||||
const typename elfcpp::Ehdr<size, big_endian>& ehdr)
|
||||
: Sized_relobj_file<size, big_endian>(name, input_file, offset, ehdr),
|
||||
special_(0), opd_ent_shndx_(), opd_ent_off_()
|
||||
special_(0), opd_ent_shndx_(), opd_ent_off_(), access_from_map_(),
|
||||
opd_valid_(false)
|
||||
{ }
|
||||
|
||||
~Powerpc_relobj()
|
||||
@ -99,14 +102,15 @@ public:
|
||||
}
|
||||
|
||||
// Return section and offset of function entry for .opd + R_OFF.
|
||||
void
|
||||
get_opd_ent(Address r_off, unsigned int* shndx, Address* value) const
|
||||
unsigned int
|
||||
get_opd_ent(Address r_off, Address* value = NULL) const
|
||||
{
|
||||
size_t ndx = this->opd_ent_ndx(r_off);
|
||||
gold_assert(ndx < this->opd_ent_shndx_.size());
|
||||
gold_assert(this->opd_ent_shndx_[ndx] != 0);
|
||||
*shndx = this->opd_ent_shndx_[ndx];
|
||||
*value = this->opd_ent_off_[ndx];
|
||||
if (value != NULL)
|
||||
*value = this->opd_ent_off_[ndx];
|
||||
return this->opd_ent_shndx_[ndx];
|
||||
}
|
||||
|
||||
// Set section and offset of function entry for .opd + R_OFF.
|
||||
@ -119,6 +123,29 @@ public:
|
||||
this->opd_ent_off_[ndx] = value;
|
||||
}
|
||||
|
||||
Access_from*
|
||||
access_from_map()
|
||||
{ return &this->access_from_map_; }
|
||||
|
||||
// Add a reference from SRC_OBJ, SRC_INDX to this object's .opd
|
||||
// section at DST_OFF.
|
||||
void
|
||||
add_reference(Object* src_obj,
|
||||
unsigned int src_indx,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr dst_off)
|
||||
{
|
||||
Section_id src_id(src_obj, src_indx);
|
||||
this->access_from_map_[dst_off].insert(src_id);
|
||||
}
|
||||
|
||||
bool
|
||||
opd_valid() const
|
||||
{ return this->opd_valid_; }
|
||||
|
||||
void
|
||||
set_opd_valid()
|
||||
{ this->opd_valid_ = true; }
|
||||
|
||||
// Examine .rela.opd to build info about function entry points.
|
||||
void
|
||||
scan_opd_relocs(size_t reloc_count,
|
||||
@ -160,6 +187,16 @@ private:
|
||||
// section and offset specified by these relocations.
|
||||
std::vector<unsigned int> opd_ent_shndx_;
|
||||
std::vector<Offset> opd_ent_off_;
|
||||
// References made to this object's .opd section when running
|
||||
// gc_process_relocs for another object, before the opd_ent vectors
|
||||
// are valid for this object.
|
||||
Access_from access_from_map_;
|
||||
// Set at the start of gc_process_relocs, when we know opd_ent
|
||||
// vectors are valid. The flag could be made atomic and set in
|
||||
// do_read_relocs with memory_order_release and then tested with
|
||||
// memory_order_acquire, potentially resulting in fewer entries in
|
||||
// access_from_map_.
|
||||
bool opd_valid_;
|
||||
};
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@ -340,6 +377,24 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||
unsigned int
|
||||
plt_entry_size() const;
|
||||
|
||||
// Add any special sections for this symbol to the gc work list.
|
||||
// For powerpc64, this adds the code section of a function
|
||||
// descriptor.
|
||||
void
|
||||
do_gc_mark_symbol(Symbol_table* symtab, Symbol* sym) const;
|
||||
|
||||
// Handle target specific gc actions when adding a gc reference from
|
||||
// SRC_OBJ, SRC_SHNDX to a location specified by DST_OBJ, DST_SHNDX
|
||||
// and DST_OFF. For powerpc64, this adds a referenc to the code
|
||||
// section of a function descriptor.
|
||||
void
|
||||
do_gc_add_reference(Symbol_table* symtab,
|
||||
Object* src_obj,
|
||||
unsigned int src_shndx,
|
||||
Object* dst_obj,
|
||||
unsigned int dst_shndx,
|
||||
Address dst_off) const;
|
||||
|
||||
private:
|
||||
|
||||
// The class which scans relocations.
|
||||
@ -2913,6 +2968,33 @@ Target_powerpc<size, big_endian>::gc_process_relocs(
|
||||
{
|
||||
typedef Target_powerpc<size, big_endian> Powerpc;
|
||||
typedef typename Target_powerpc<size, big_endian>::Scan Scan;
|
||||
Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<Powerpc_relobj<size, big_endian>*>(object);
|
||||
if (size == 64)
|
||||
ppc_object->set_opd_valid();
|
||||
if (size == 64 && data_shndx == ppc_object->opd_shndx())
|
||||
{
|
||||
typename Powerpc_relobj<size, big_endian>::Access_from::iterator p;
|
||||
for (p = ppc_object->access_from_map()->begin();
|
||||
p != ppc_object->access_from_map()->end();
|
||||
++p)
|
||||
{
|
||||
Address dst_off = p->first;
|
||||
unsigned int dst_indx = ppc_object->get_opd_ent(dst_off);
|
||||
typename Powerpc_relobj<size, big_endian>::Section_refs::iterator s;
|
||||
for (s = p->second.begin(); s != p->second.end(); ++s)
|
||||
{
|
||||
Object* src_obj = s->first;
|
||||
unsigned int src_indx = s->second;
|
||||
symtab->gc()->add_reference(src_obj, src_indx,
|
||||
ppc_object, dst_indx);
|
||||
}
|
||||
p->second.clear();
|
||||
}
|
||||
ppc_object->access_from_map()->clear();
|
||||
// Don't look at .opd relocs as .opd will reference everything.
|
||||
return;
|
||||
}
|
||||
|
||||
gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan,
|
||||
typename Target_powerpc::Relocatable_size_for_reloc>(
|
||||
@ -2929,6 +3011,65 @@ Target_powerpc<size, big_endian>::gc_process_relocs(
|
||||
plocal_symbols);
|
||||
}
|
||||
|
||||
// Handle target specific gc actions when adding a gc reference from
|
||||
// SRC_OBJ, SRC_SHNDX to a location specified by DST_OBJ, DST_SHNDX
|
||||
// and DST_OFF. For powerpc64, this adds a referenc to the code
|
||||
// section of a function descriptor.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Target_powerpc<size, big_endian>::do_gc_add_reference(
|
||||
Symbol_table* symtab,
|
||||
Object* src_obj,
|
||||
unsigned int src_shndx,
|
||||
Object* dst_obj,
|
||||
unsigned int dst_shndx,
|
||||
Address dst_off) const
|
||||
{
|
||||
Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<Powerpc_relobj<size, big_endian>*>(dst_obj);
|
||||
if (size == 64 && dst_shndx == ppc_object->opd_shndx())
|
||||
{
|
||||
if (ppc_object->opd_valid())
|
||||
{
|
||||
dst_shndx = ppc_object->get_opd_ent(dst_off);
|
||||
symtab->gc()->add_reference(src_obj, src_shndx, dst_obj, dst_shndx);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we haven't run scan_opd_relocs, we must delay
|
||||
// processing this function descriptor reference.
|
||||
ppc_object->add_reference(src_obj, src_shndx, dst_off);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add any special sections for this symbol to the gc work list.
|
||||
// For powerpc64, this adds the code section of a function
|
||||
// descriptor.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
void
|
||||
Target_powerpc<size, big_endian>::do_gc_mark_symbol(
|
||||
Symbol_table* symtab,
|
||||
Symbol* sym) const
|
||||
{
|
||||
if (size == 64)
|
||||
{
|
||||
Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<Powerpc_relobj<size, big_endian>*>(sym->object());
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = sym->shndx(&is_ordinary);
|
||||
if (is_ordinary && shndx == ppc_object->opd_shndx())
|
||||
{
|
||||
Sized_symbol<size>* gsym = symtab->get_sized_symbol<size>(sym);
|
||||
Address dst_off = gsym->value();
|
||||
unsigned int dst_indx = ppc_object->get_opd_ent(dst_off);
|
||||
symtab->gc()->worklist().push(Section_id(ppc_object, dst_indx));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Scan relocations for a section.
|
||||
|
||||
template<int size, bool big_endian>
|
||||
@ -3064,7 +3205,7 @@ Target_powerpc<size, big_endian>::symval_for_branch(
|
||||
if (value >= opd_addr && value < opd_addr + symobj->section_size(shndx))
|
||||
{
|
||||
Address sec_off;
|
||||
symobj->get_opd_ent(value - opd_addr, dest_shndx, &sec_off);
|
||||
*dest_shndx = symobj->get_opd_ent(value - opd_addr, &sec_off);
|
||||
Address sec_addr = symobj->get_output_section_offset(*dest_shndx);
|
||||
gold_assert(sec_addr != invalid_address);
|
||||
sec_addr += symobj->output_section(*dest_shndx)->address();
|
||||
|
@ -577,14 +577,7 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout)
|
||||
if (sym->source() == Symbol::FROM_OBJECT
|
||||
&& !sym->object()->is_dynamic())
|
||||
{
|
||||
Relobj* obj = static_cast<Relobj*>(sym->object());
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = sym->shndx(&is_ordinary);
|
||||
if (is_ordinary)
|
||||
{
|
||||
gold_assert(this->gc_ != NULL);
|
||||
this->gc_->worklist().push(Section_id(obj, shndx));
|
||||
}
|
||||
this->gc_mark_symbol(sym);
|
||||
}
|
||||
}
|
||||
|
||||
@ -601,14 +594,7 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout)
|
||||
&& sym->source() == Symbol::FROM_OBJECT
|
||||
&& !sym->object()->is_dynamic())
|
||||
{
|
||||
Relobj* obj = static_cast<Relobj*>(sym->object());
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = sym->shndx(&is_ordinary);
|
||||
if (is_ordinary)
|
||||
{
|
||||
gold_assert(this->gc_ != NULL);
|
||||
this->gc_->worklist().push(Section_id(obj, shndx));
|
||||
}
|
||||
this->gc_mark_symbol(sym);
|
||||
}
|
||||
}
|
||||
|
||||
@ -622,14 +608,7 @@ Symbol_table::gc_mark_undef_symbols(Layout* layout)
|
||||
if (sym->source() == Symbol::FROM_OBJECT
|
||||
&& !sym->object()->is_dynamic())
|
||||
{
|
||||
Relobj* obj = static_cast<Relobj*>(sym->object());
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = sym->shndx(&is_ordinary);
|
||||
if (is_ordinary)
|
||||
{
|
||||
gold_assert(this->gc_ != NULL);
|
||||
this->gc_->worklist().push(Section_id(obj, shndx));
|
||||
}
|
||||
this->gc_mark_symbol(sym);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -638,14 +617,14 @@ void
|
||||
Symbol_table::gc_mark_symbol(Symbol* sym)
|
||||
{
|
||||
// Add the object and section to the work list.
|
||||
Relobj* obj = static_cast<Relobj*>(sym->object());
|
||||
bool is_ordinary;
|
||||
unsigned int shndx = sym->shndx(&is_ordinary);
|
||||
if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
|
||||
{
|
||||
gold_assert(this->gc_!= NULL);
|
||||
this->gc_->worklist().push(Section_id(obj, shndx));
|
||||
this->gc_->worklist().push(Section_id(sym->object(), shndx));
|
||||
}
|
||||
parameters->target().gc_mark_symbol(this, sym);
|
||||
}
|
||||
|
||||
// When doing garbage collection, keep symbols that have been seen in
|
||||
|
@ -421,6 +421,11 @@ class Target
|
||||
size_t* plen) const
|
||||
{ return this->do_output_section_name(relobj, name, plen); }
|
||||
|
||||
// Add any special sections for this symbol to the gc work list.
|
||||
void
|
||||
gc_mark_symbol(Symbol_table* symtab, Symbol* sym) const
|
||||
{ this->do_gc_mark_symbol(symtab, sym); }
|
||||
|
||||
protected:
|
||||
// This struct holds the constant information for a child class. We
|
||||
// use a struct to avoid the overhead of virtual function calls for
|
||||
@ -669,6 +674,11 @@ class Target
|
||||
do_output_section_name(const Relobj*, const char*, size_t*) const
|
||||
{ return NULL; }
|
||||
|
||||
// This may be overridden by the child class.
|
||||
virtual void
|
||||
do_gc_mark_symbol(Symbol_table*, Symbol*) const
|
||||
{ }
|
||||
|
||||
private:
|
||||
// The implementations of the four do_make_elf_object virtual functions are
|
||||
// almost identical except for their sizes and endianness. We use a template.
|
||||
@ -935,6 +945,21 @@ class Sized_target : public Target
|
||||
section_size_type /* view_size */)
|
||||
{ gold_unreachable(); }
|
||||
|
||||
// Handle target specific gc actions when adding a gc reference from
|
||||
// SRC_OBJ, SRC_SHNDX to a location specified by DST_OBJ, DST_SHNDX
|
||||
// and DST_OFF.
|
||||
void
|
||||
gc_add_reference(Symbol_table* symtab,
|
||||
Object* src_obj,
|
||||
unsigned int src_shndx,
|
||||
Object* dst_obj,
|
||||
unsigned int dst_shndx,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr dst_off) const
|
||||
{
|
||||
this->do_gc_add_reference(symtab, src_obj, src_shndx,
|
||||
dst_obj, dst_shndx, dst_off);
|
||||
}
|
||||
|
||||
protected:
|
||||
Sized_target(const Target::Target_info* pti)
|
||||
: Target(pti)
|
||||
@ -946,6 +971,13 @@ class Sized_target : public Target
|
||||
// Set the EI_OSABI field if requested.
|
||||
virtual void
|
||||
do_adjust_elf_header(unsigned char*, int) const;
|
||||
|
||||
// Handle target specific gc actions when adding a gc reference.
|
||||
virtual void
|
||||
do_gc_add_reference(Symbol_table*, Object*, unsigned int,
|
||||
Object*, unsigned int,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr) const
|
||||
{ }
|
||||
};
|
||||
|
||||
} // End namespace gold.
|
||||
|
Loading…
Reference in New Issue
Block a user