Take symbol versions in account when computing added/removed decls

* include/abg-corpus.h
	(corpus::lookup_{function,variable}_symbol): Add an overload
	declaration that takes the version of the symbol to lookup.
	* src/abg-comparison.cc
	(corpus_diff::priv::ensure_lookup_tables_populated): So when looking
	up the corpora for symbols, take their versions in account.
	* src/abg-corpus.cc (corpus::lookup_{function,variable}_symbol):
	Add an overload definition that takes the version of the symbol to
	lookup.
	(symtab_build_visitor_type::build_id): New
	member functions.
	(corpus::priv::build_public_decl_table): Use the new member
	functions above.
	* src/abg-ir.cc (elf_symbol::version::operator==): Do not take the
	is_default flag in account when comparing two symbol versions.
	* libtest12-v{0,1}.so: New test input files.
	* libtest12-v{0,1}.c: Source code for the test input files.
	* test12-version-script: Version script to build the files above.
	* test12-report.txt: Test input file.
	* tests/Makefile.am: Add the new test input files above to the
	source distribution.
	* tests/test-diff-dwarf.cc (in_out_specs[]): Add an entry to this
	table for the new test input files.

Signed-off-by: Dodji Seketeli <dodji@redhat.com>
This commit is contained in:
Dodji Seketeli 2014-08-25 23:06:18 +02:00
parent 5c493339c6
commit b13345fd86
12 changed files with 207 additions and 11 deletions

View File

@ -113,9 +113,17 @@ public:
const elf_symbol_sptr
lookup_function_symbol(const string& n) const;
const elf_symbol_sptr
lookup_function_symbol(const string& symbol_name,
const string& symbol_version) const;
const elf_symbol_sptr
lookup_variable_symbol(const string& n) const;
const elf_symbol_sptr
lookup_variable_symbol(const string& symbol_name,
const string& symbol_version) const;
const functions&
get_functions() const;

View File

@ -6258,7 +6258,8 @@ corpus_diff::priv::ensure_lookup_tables_populated()
for (string_function_ptr_map::const_iterator i = deleted_fns_.begin();
i != deleted_fns_.end();
++i)
if (second_->lookup_function_symbol(i->first))
if (second_->lookup_function_symbol(i->first,
i->second->get_symbol()->get_version().str()))
to_delete.push_back(i->first);
for (vector<string>::const_iterator i = to_delete.begin();
@ -6272,7 +6273,8 @@ corpus_diff::priv::ensure_lookup_tables_populated()
for (string_function_ptr_map::const_iterator i = added_fns_.begin();
i != added_fns_.end();
++i)
if (first_->lookup_function_symbol(i->first))
if (first_->lookup_function_symbol(i->first,
i->second->get_symbol()->get_version().str()))
to_delete.push_back(i->first);
for (vector<string>::const_iterator i = to_delete.begin();
@ -6345,7 +6347,8 @@ corpus_diff::priv::ensure_lookup_tables_populated()
for (string_var_ptr_map::const_iterator i = deleted_vars_.begin();
i != deleted_vars_.end();
++i)
if (second_->lookup_variable_symbol(i->first))
if (second_->lookup_variable_symbol(i->first,
i->second->get_symbol()->get_version().str()))
to_delete.push_back(i->first);
for (vector<string>::const_iterator i = to_delete.begin();
@ -6359,7 +6362,8 @@ corpus_diff::priv::ensure_lookup_tables_populated()
for (string_var_ptr_map::const_iterator i = added_vars_.begin();
i != added_vars_.end();
++i)
if (first_->lookup_variable_symbol(i->first))
if (first_->lookup_variable_symbol(i->first,
i->second->get_symbol()->get_version().str()))
to_delete.push_back(i->first);
for (vector<string>::const_iterator i = to_delete.begin();

View File

@ -188,6 +188,78 @@ public:
fns_map()
{return functions_map;}
/// Build a string that uniquely identifies a function_decl inside
/// one corpus.
///
/// That ID is either the name of the symbol of the function,
/// concatenated with its version name, if the symbol exists.
/// Otherwise, it's the linkage name of the function, if it exists.
/// Otherwise it's the pretty representation ofthe function.
///
/// @param fn the function to build the id for.
///
/// @return the unique ID.
string
build_id(const function_decl& fn)
{
if (elf_symbol_sptr s = fn.get_symbol())
return s->get_id_string();
else if (!fn.get_linkage_name().empty())
return fn.get_linkage_name();
return fn.get_pretty_representation();
}
/// Build a string that uniquely identifies a var_decl inside
/// one corpus.
///
/// That ID is either the name of the symbol of the variable,
/// concatenated with its version name, if the symbol exists.
/// Otherwise, it's the linkage name of the varible, if it exists.
/// Otherwise it's the pretty representation ofthe variable.
///
/// @param var the function to build the id for.
///
/// @return the unique ID.
string
build_id(const var_decl& var)
{
if (elf_symbol_sptr s = var.get_symbol())
return s->get_id_string();
else if (!var.get_linkage_name().empty())
return var.get_linkage_name();
return var.get_pretty_representation();
}
/// Build a string that uniquely identifies a function_decl inside
/// one corpus.
///
/// That ID is either the name of the symbol of the function,
/// concatenated with its version name, if the symbol exists.
/// Otherwise, it's the linkage name of the function, if it exists.
/// Otherwise it's the pretty representation ofthe function.
///
/// @param fn the function to build the id for.
///
/// @return the unique ID.
string
build_id(const function_decl* fn)
{return build_id(*fn);}
/// Build a string that uniquely identifies a var_decl inside
/// one corpus.
///
/// That ID is either the name of the symbol of the variable,
/// concatenated with its version name, if the symbol exists.
/// Otherwise, it's the linkage name of the varible, if it exists.
/// Otherwise it's the pretty representation ofthe variable.
///
/// @param var the function to build the id for.
///
/// @return the unique ID.
string
build_id(const var_decl* fn)
{return build_id(*fn);}
/// Test if a given function name is in the map of strings and
/// function pointer.
///
@ -564,9 +636,7 @@ corpus::priv::build_public_decl_table()
i != v.wip_fns.end();
++i)
{
string n = (*i)->get_linkage_name();
if (n.empty())
n = (*i)->get_pretty_representation();
string n = v.build_id(*i);
assert(!n.empty());
if (origin_ == DWARF_ORIGIN
@ -588,9 +658,7 @@ corpus::priv::build_public_decl_table()
i != v.wip_vars.end();
++i)
{
string n = (*i)->get_linkage_name();
if (n.empty())
n = (*i)->get_pretty_representation();
string n = v.build_id(*i);
assert(!n.empty());
if (origin_ == DWARF_ORIGIN
@ -771,6 +839,35 @@ corpus::lookup_function_symbol(const string& n) const
return it->second[0];
}
/// Look in the function symbols map for a symbol with a given name.
///
/// @param symbol_name the name of the symbol to look for.
///
/// @param symbol_version the version of the symbol to look for.
///
/// return the symbol with the name @p symbol_name and with the name
/// @p symbol_version, or nil if no symbol has been found with that
/// name and version.
const elf_symbol_sptr
corpus::lookup_function_symbol(const string& symbol_name,
const string& symbol_version) const
{
if (!get_fun_symbol_map_sptr())
return elf_symbol_sptr();
string_elf_symbols_map_type::const_iterator it =
get_fun_symbol_map_sptr()->find(symbol_name);
if ( it == get_fun_symbol_map_sptr()->end())
return elf_symbol_sptr();
for (elf_symbols::const_iterator s = it->second.begin();
s != it->second.end();
++s)
if ((*s)->get_version().str() == symbol_version)
return *s;
return elf_symbol_sptr();
}
/// Look in the variable symbols map for a symbol with a given name.
///
/// @param n the name of the symbol to look for.
@ -789,6 +886,33 @@ corpus::lookup_variable_symbol(const string& n) const
return it->second[0];
}
/// Look in the variable symbols map for a symbol with a given name.
///
/// @param symbol_name the name of the symbol to look for.
///
/// @param symbol_version the version of the symbol to look for.
///
/// return the first symbol with the name @p n.
const elf_symbol_sptr
corpus::lookup_variable_symbol(const string& symbol_name,
const string& symbol_version) const
{
if (!get_var_symbol_map_sptr())
return elf_symbol_sptr();
string_elf_symbols_map_type::const_iterator it =
get_var_symbol_map_sptr()->find(symbol_name);
if ( it == get_var_symbol_map_sptr()->end())
return elf_symbol_sptr();
for (elf_symbols::const_iterator s = it->second.begin();
s != it->second.end();
++s)
if ((*s)->get_version().str() == symbol_version)
return *s;
return elf_symbol_sptr();
}
/// Build and return the functions public decl table of the current corpus.
///
/// The function public decl tables is a vector of all the functions and

View File

@ -864,7 +864,7 @@ elf_symbol::version::is_empty() const
/// @return true iff the current version equals @p o.
bool
elf_symbol::version::operator==(const elf_symbol::version& o) const
{return is_default() == o.is_default() && str() == o.str();}
{return str() == o.str();}
/// Assign a version to the current one.
///

View File

@ -186,6 +186,12 @@ data/test-diff-dwarf/test11-v0.o \
data/test-diff-dwarf/test11-v1.cc \
data/test-diff-dwarf/test11-v1.o \
data/test-diff-dwarf/test11-report.txt \
data/test-diff-dwarf/test12-v0.c \
data/test-diff-dwarf/libtest12-v0.so \
data/test-diff-dwarf/test12-v1.c \
data/test-diff-dwarf/libtest12-v1.so \
data/test-diff-dwarf/test12-version-script \
data/test-diff-dwarf/test12-report.txt \
\
data/test-read-dwarf/test0 \
data/test-read-dwarf/test0.abi \

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
Functions changes summary: 0 Removed, 0 Changed, 1 Added function
Variables changes summary: 0 Removed, 0 Changed, 0 Added variable
1 Added function:
'function int _foo3(int, int)'

View File

@ -0,0 +1,12 @@
/* To compile this, type:
gcc -shared -Wl,--version-script=test12-version-script -o libtest12-v0.so test12-v0.c
*/
int
_foo1(int v)
{return v + 1;}
asm(".symver _foo1,foo@VERSION_1.0");
int
_foo2(int v)
{return v + 2;}
asm(".symver _foo2,foo@@VERSION_2.0");

View File

@ -0,0 +1,17 @@
/* To compile this, type:
gcc -shared -Wl,--version-script=test12-version-script -o libtest12-v1.so test12-v1.c
*/
int
_foo1(int v)
{return v + 1;}
asm(".symver _foo1,foo@VERSION_1.0");
int
_foo2(int v)
{return v + 2;}
asm(".symver _foo2,foo@VERSION_2.0");
int
_foo3(int v, int w)
{return v + w + !2;}
asm(".symver _foo3,foo@@VERSION_3.0");

View File

@ -0,0 +1,11 @@
VERSION_1.0 {
global: foo;
};
VERSION_2.0 {
global: foo;
} VERSION_1.0;
VERSION_3.0 {
global: foo;
} VERSION_2.0;

View File

@ -134,6 +134,12 @@ InOutSpec in_out_specs[] =
"data/test-diff-dwarf/test11-report.txt",
"output/test-diff-dwarf/test11-report.txt"
},
{
"data/test-diff-dwarf/libtest12-v0.so",
"data/test-diff-dwarf/libtest12-v1.so",
"data/test-diff-dwarf/test12-report.txt",
"output/test-diff-dwarf/test12-report.txt"
},
// This should be the last entry
{NULL, NULL, NULL, NULL}
};