aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 00:16:43 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2023-12-14 00:16:43 +0000
commit16878c9d3b170afb0050375442a4e07bf7ce44f9 (patch)
tree28f4a7080374fadd9599080be9c3d1d31bf01211
parent0c75de504d41ab673214f3b676483bb3a2db0171 (diff)
parent4ffc20011f1b68af77efec5a6f3b352248f7bc25 (diff)
downloadstg-android14-qpr2-s1-release.tar.gz
Change-Id: I99a7690e94d8c8c08725a6612c92b02da726eac4
-rw-r--r--CMakeLists.txt11
-rw-r--r--README.md2
-rw-r--r--doc/stg.md2
-rw-r--r--dwarf_processor.cc16
-rw-r--r--dwarf_wrappers.cc30
-rw-r--r--error.h10
-rw-r--r--filter.cc2
-rw-r--r--filter_test.cc3
-rw-r--r--input.cc25
-rw-r--r--stg.cc13
-rw-r--r--stgdiff.cc2
-rw-r--r--test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_flat2
-rw-r--r--test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_plain2
-rw-r--r--test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_small2
-rw-r--r--test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_viz50
-rw-r--r--test_cases/diff_tests/member/pointer_to_member.1.cc5
-rw-r--r--test_cases/info_tests/member/expected/pointer_to_member_cc.elf_stg14
-rw-r--r--test_cases/info_tests/member/pointer_to_member.cc3
-rw-r--r--test_cases/info_tests/source_filter/expected/type_roots_cc.elf_stg5
-rw-r--r--test_cases/info_tests/source_filter/expected/types_cc.elf_stg (renamed from test_cases/info_tests/source_filter/expected/composite_and_enum_cc.elf_stg)23
-rw-r--r--test_cases/info_tests/source_filter/type_roots.cc (renamed from test_cases/info_tests/source_filter/composite_and_enum.cc)3
-rw-r--r--test_cases/info_tests/source_filter/types.cc30
-rw-r--r--test_cases/info_tests/symbol/expected/tls_emulated_c.elf_stg26
-rw-r--r--test_cases/info_tests/symbol/expected/tls_emulated_cc.elf_stg38
-rw-r--r--test_cases/info_tests/symbol/expected/version_definition_c.elf_stg2
-rw-r--r--test_cases/info_tests/symbol/version_definition.c8
26 files changed, 274 insertions, 55 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5dda38c..bb112da 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -27,6 +27,17 @@ set(CMAKE_CXX_STANDARD 20)
add_compile_options(-fstrict-enums -Wall -Wextra)
+set(MINIMUM_GNU_VERSION 11)
+set(MINIMUM_Clang_VERSION 15)
+
+# Note, the quotes around the variable are significant. If we use a compiler
+# that does not resolve to a definition above, the empty string corresponds to
+# a version where all components are omitted and hence treated as zero.
+if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS "${MINIMUM_${CMAKE_CXX_COMPILER_ID}_VERSION}")
+ message(FATAL_ERROR "Unsupported Compiler Version!\n"
+ "Need at least ${CMAKE_CXX_COMPILER_ID} ${MINIMUM_${CMAKE_CXX_COMPILER_ID}_VERSION}")
+endif()
+
if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
# GCC has problems detecting "no-return" switches and destructors.
add_compile_options(-Wno-return-type)
diff --git a/README.md b/README.md
index da17a12..9906ce8 100644
--- a/README.md
+++ b/README.md
@@ -37,7 +37,7 @@ Instructions are included for local and Docker builds.
### Dependencies
-STG is written in C++20. It is known to compile with GCC 11, Clang 14 or
+STG is written in C++20. It is known to compile with GCC 11, Clang 15 or
later versions.
| *Dependency* | *Debian* | *RedHat* |
diff --git a/doc/stg.md b/doc/stg.md
index 31f9ab5..ec97448 100644
--- a/doc/stg.md
+++ b/doc/stg.md
@@ -98,7 +98,7 @@ There are two types of filters that can be applied to STG output:
File filters are only applicable to ELF binary objects containing DWARF with
source location information; any other kind of input will be unaffected.
-2. `-S|--symbols|--symbol-filter <filter>`
+1. `-S|--symbols|--symbol-filter <filter>`
Filter ELF symbols by name (which may include a `@version` or `@@version`
suffix).
diff --git a/dwarf_processor.cc b/dwarf_processor.cc
index a8e41bf..48d6e26 100644
--- a/dwarf_processor.cc
+++ b/dwarf_processor.cc
@@ -301,6 +301,17 @@ class Processor {
private:
void Process(Entry& entry) {
+ try {
+ return ProcessInternal(entry);
+ } catch (Exception& e) {
+ std::ostringstream os;
+ os << "processing DIE " << Hex(entry.GetOffset());
+ e.Add(os.str());
+ throw;
+ }
+ }
+
+ void ProcessInternal(Entry& entry) {
++result_.processed_entries;
auto tag = entry.GetTag();
switch (tag) {
@@ -424,6 +435,11 @@ class Processor {
const std::string type_name = scope_ + GetName(entry);
auto referred_type_id = GetIdForReferredType(MaybeGetReferredType(entry));
const Id id = AddProcessedNode<Typedef>(entry, type_name, referred_type_id);
+ if (!ShouldKeepDefinition(entry, type_name)) {
+ // We always model (and keep) typedef definitions. But we should exclude
+ // filtered out types from being type roots.
+ return;
+ }
AddNamedTypeNode(id);
}
diff --git a/dwarf_wrappers.cc b/dwarf_wrappers.cc
index e5780eb..d13d7b8 100644
--- a/dwarf_wrappers.cc
+++ b/dwarf_wrappers.cc
@@ -129,13 +129,19 @@ struct Expression {
size_t length = 0;
};
-Expression GetExpression(Dwarf_Attribute& attribute) {
+std::optional<Expression> MaybeGetExpression(Dwarf_Attribute& attribute) {
Expression result;
Check(dwarf_getlocation(&attribute, &result.atoms, &result.length) ==
kReturnOk) << "dwarf_getlocation returned error";
- Check(result.atoms != nullptr && result.length > 0)
- << "dwarf_getlocation returned empty expression";
+ // If no location attribute is present or has an empty location description,
+ // the variable is present in the source but not in the object code.
+ // So zero length expression is equivalent of no location attribute.
+ if (result.length == 0) {
+ return std::nullopt;
+ }
+ Check(result.atoms != nullptr)
+ << "dwarf_getlocation returned non-empty expression with NULL atoms";
return result;
}
@@ -298,7 +304,11 @@ std::optional<Entry> Entry::MaybeGetReference(uint32_t attribute) {
namespace {
std::optional<Address> GetAddressFromLocation(Dwarf_Attribute& attribute) {
- const auto expression = GetExpression(attribute);
+ const auto expression_opt = MaybeGetExpression(attribute);
+ if (!expression_opt) {
+ return {};
+ }
+ const Expression& expression = *expression_opt;
Dwarf_Attribute result_attribute;
if (dwarf_getlocation_attr(&attribute, expression.atoms, &result_attribute) ==
@@ -360,7 +370,11 @@ std::optional<uint64_t> Entry::MaybeGetMemberByteOffset() {
}
// Parse location expression
- const auto expression = GetExpression(attribute.value());
+ const auto expression_opt = MaybeGetExpression(attribute.value());
+ if (!expression_opt) {
+ return {};
+ }
+ const Expression& expression = *expression_opt;
// Parse virtual base classes offset, which looks like this:
// [0] = DW_OP_dup
@@ -394,7 +408,11 @@ std::optional<uint64_t> Entry::MaybeGetVtableOffset() {
}
// Parse location expression
- const Expression expression = GetExpression(attribute.value());
+ const auto expression_opt = MaybeGetExpression(attribute.value());
+ if (!expression_opt) {
+ return {};
+ }
+ const Expression& expression = *expression_opt;
// We expect compilers to produce expression with one constant operand
if (expression.length == 1) {
diff --git a/error.h b/error.h
index 6eed80e..5ca6c57 100644
--- a/error.h
+++ b/error.h
@@ -32,14 +32,20 @@ namespace stg {
class Exception : public std::exception {
public:
- explicit Exception(const std::string& message) : message_(message) {}
+ explicit Exception(const std::string& message) {
+ Add(message);
+ }
const char* what() const noexcept(true) final {
return message_.c_str();
}
+ void Add(const std::string& message) {
+ (message_ += message) += '\n';
+ }
+
private:
- const std::string message_;
+ std::string message_;
};
class Check {
diff --git a/filter.cc b/filter.cc
index d21dbcb..aa6f10a 100644
--- a/filter.cc
+++ b/filter.cc
@@ -157,7 +157,7 @@ class SetFilter : public Filter {
const Items items_;
};
-static const char* kTokenCharacters = ":!()&|";
+const char* kTokenCharacters = ":!()&|";
// Split a filter expression into tokens.
//
diff --git a/filter_test.cc b/filter_test.cc
index 7666965..2be2bcc 100644
--- a/filter_test.cc
+++ b/filter_test.cc
@@ -19,7 +19,6 @@
#include "filter.h"
-#include <sstream>
#include <string>
#include <tuple>
#include <vector>
@@ -52,7 +51,6 @@ TEST_CASE("bad syntax cases") {
};
for (const auto& expression : cases) {
- std::ostringstream os;
GIVEN("filter: " + expression) {
CHECK_THROWS(stg::MakeFilter(expression));
}
@@ -104,7 +102,6 @@ TEST_CASE("hand-curated cases") {
};
for (const auto& [expression, ins, outs] : cases) {
- std::ostringstream os;
GIVEN("filter: " + expression) {
auto filter = stg::MakeFilter(expression);
for (const auto& in : ins) {
diff --git a/input.cc b/input.cc
index c396b47..f30cdca 100644
--- a/input.cc
+++ b/input.cc
@@ -20,10 +20,12 @@
#include "input.h"
#include <memory>
+#include <sstream>
#include "abigail_reader.h"
#include "btf_reader.h"
#include "elf_reader.h"
+#include "error.h"
#include "filter.h"
#include "graph.h"
#include "metrics.h"
@@ -32,9 +34,11 @@
namespace stg {
-Id Read(Graph& graph, InputFormat format, const char* input,
- ReadOptions options, const std::unique_ptr<Filter>& file_filter,
- Metrics& metrics) {
+namespace {
+
+Id ReadInternal(Graph& graph, InputFormat format, const char* input,
+ ReadOptions options, const std::unique_ptr<Filter>& file_filter,
+ Metrics& metrics) {
switch (format) {
case InputFormat::ABI: {
Time read(metrics, "read ABI");
@@ -55,4 +59,19 @@ Id Read(Graph& graph, InputFormat format, const char* input,
}
}
+} // namespace
+
+Id Read(Graph& graph, InputFormat format, const char* input,
+ ReadOptions options, const std::unique_ptr<Filter>& file_filter,
+ Metrics& metrics) {
+ try {
+ return ReadInternal(graph, format, input, options, file_filter, metrics);
+ } catch (Exception& e) {
+ std::ostringstream os;
+ os << "processing file '" << input << '\'';
+ e.Add(os.str());
+ throw;
+ }
+}
+
} // namespace stg
diff --git a/stg.cc b/stg.cc
index 00dc9bb..82a372e 100644
--- a/stg.cc
+++ b/stg.cc
@@ -123,7 +123,7 @@ int main(int argc, char* argv[]) {
std::unique_ptr<stg::Filter> opt_symbol_filter;
stg::ReadOptions opt_read_options;
stg::InputFormat opt_input_format = stg::InputFormat::ABI;
- std::vector<const char*> inputs;
+ std::vector<std::pair<stg::InputFormat, const char*>> inputs;
std::vector<const char*> outputs;
static option opts[] = {
{"metrics", no_argument, nullptr, 'm'},
@@ -189,7 +189,7 @@ int main(int argc, char* argv[]) {
opt_input_format = stg::InputFormat::STG;
break;
case 1:
- inputs.push_back(argument);
+ inputs.emplace_back(opt_input_format, argument);
break;
case 'o':
if (strcmp(argument, "-") == 0) {
@@ -207,10 +207,9 @@ int main(int argc, char* argv[]) {
stg::Metrics metrics;
std::vector<stg::Id> roots;
roots.reserve(inputs.size());
- for (auto input : inputs) {
- roots.push_back(stg::Read(graph, opt_input_format, input,
- opt_read_options, opt_file_filter,
- metrics));
+ for (auto& [format, input] : inputs) {
+ roots.push_back(stg::Read(graph, format, input, opt_read_options,
+ opt_file_filter, metrics));
}
stg::Id root =
roots.size() == 1 ? roots[0] : stg::Merge(graph, roots, metrics);
@@ -235,7 +234,7 @@ int main(int argc, char* argv[]) {
}
return 0;
} catch (const stg::Exception& e) {
- std::cerr << e.what() << '\n';
+ std::cerr << e.what();
return 1;
}
}
diff --git a/stgdiff.cc b/stgdiff.cc
index 51dda88..18cc733 100644
--- a/stgdiff.cc
+++ b/stgdiff.cc
@@ -270,7 +270,7 @@ int main(int argc, char* argv[]) {
}
return status;
} catch (const stg::Exception& e) {
- std::cerr << e.what() << '\n';
+ std::cerr << e.what();
return 1;
}
}
diff --git a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_flat b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_flat
index 73846d7..59e5a0e 100644
--- a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_flat
+++ b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_flat
@@ -1,5 +1,7 @@
function symbol 'int struct S::* s2()' {_Z2s2v} was added
+function symbol 'int s10(int struct S::*)' {_Z3s10M1Si} was added
+
function symbol 'void pmz_fun()' {_Z7pmz_funv} was added
variable symbol 'char struct Y::* pmc' was added
diff --git a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_plain b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_plain
index 73846d7..59e5a0e 100644
--- a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_plain
+++ b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_plain
@@ -1,5 +1,7 @@
function symbol 'int struct S::* s2()' {_Z2s2v} was added
+function symbol 'int s10(int struct S::*)' {_Z3s10M1Si} was added
+
function symbol 'void pmz_fun()' {_Z7pmz_funv} was added
variable symbol 'char struct Y::* pmc' was added
diff --git a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_small b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_small
index 73846d7..59e5a0e 100644
--- a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_small
+++ b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_small
@@ -1,5 +1,7 @@
function symbol 'int struct S::* s2()' {_Z2s2v} was added
+function symbol 'int s10(int struct S::*)' {_Z3s10M1Si} was added
+
function symbol 'void pmz_fun()' {_Z7pmz_funv} was added
variable symbol 'char struct Y::* pmc' was added
diff --git a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_viz b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_viz
index 31262c8..292ca80 100644
--- a/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_viz
+++ b/test_cases/diff_tests/member/expected/pointer_to_member_cc.o_o_viz
@@ -2,46 +2,48 @@ digraph "ABI diff" {
"0" [shape=rectangle, label="'interface'"]
"1" [color=red, label="added(int struct S::* s2() {_Z2s2v})"]
"0" -> "1" [label=""]
- "2" [color=red, label="added(void pmz_fun() {_Z7pmz_funv})"]
+ "2" [color=red, label="added(int s10(int struct S::*) {_Z3s10M1Si})"]
"0" -> "2" [label=""]
- "3" [color=red, label="added(char struct Y::* pmc)"]
+ "3" [color=red, label="added(void pmz_fun() {_Z7pmz_funv})"]
"0" -> "3" [label=""]
- "4" [color=red, label="added(int union U::* pmcu)"]
+ "4" [color=red, label="added(char struct Y::* pmc)"]
"0" -> "4" [label=""]
- "5" [color=red, label="added(double struct X::* pmd)"]
+ "5" [color=red, label="added(int union U::* pmcu)"]
"0" -> "5" [label=""]
- "6" [color=red, label="added(void(struct X::* pmf)(struct X*, int))"]
+ "6" [color=red, label="added(double struct X::* pmd)"]
"0" -> "6" [label=""]
- "7" [color=red, label="added(int struct X::* pmi)"]
+ "7" [color=red, label="added(void(struct X::* pmf)(struct X*, int))"]
"0" -> "7" [label=""]
- "8" [color=red, label="added(int union U::* pmu)"]
+ "8" [color=red, label="added(int struct X::* pmi)"]
"0" -> "8" [label=""]
- "9" [color=red, label="added(int struct { int t; }::* pmy)"]
+ "9" [color=red, label="added(int union U::* pmu)"]
"0" -> "9" [label=""]
- "10" [color=red, label="added(int struct S::* s0)"]
+ "10" [color=red, label="added(int struct { int t; }::* pmy)"]
"0" -> "10" [label=""]
- "11" [color=red, label="added(int struct S::** s1)"]
+ "11" [color=red, label="added(int struct S::* s0)"]
"0" -> "11" [label=""]
- "12" [color=red, label="added(int struct S::*(* s3)())"]
+ "12" [color=red, label="added(int struct S::** s1)"]
"0" -> "12" [label=""]
- "13" [color=red, label="added(int struct S::* s4[7])"]
+ "13" [color=red, label="added(int struct S::*(* s3)())"]
"0" -> "13" [label=""]
- "14" [color=red, label="added(int* struct S::* s5)"]
+ "14" [color=red, label="added(int struct S::* s4[7])"]
"0" -> "14" [label=""]
- "15" [color=red, label="added(int(* struct S::* s6)())"]
+ "15" [color=red, label="added(int* struct S::* s5)"]
"0" -> "15" [label=""]
- "16" [color=red, label="added(int(struct S::* s7)(struct S*))"]
+ "16" [color=red, label="added(int(* struct S::* s6)())"]
"0" -> "16" [label=""]
- "17" [color=red, label="added(int(struct S::* s8)[7])"]
+ "17" [color=red, label="added(int(struct S::* s7)(struct S*))"]
"0" -> "17" [label=""]
- "18" [color=red, label="added(const int struct S::* volatile s9)"]
+ "18" [color=red, label="added(int(struct S::* s8)[7])"]
"0" -> "18" [label=""]
- "19" [label="'char struct A::* diff' -> 'int struct B::* diff'"]
- "20" [label="'char struct A::*' -> 'int struct B::*'"]
- "21" [color=red, label="'struct A' -> 'struct B'"]
- "20" -> "21" [label="containing"]
- "22" [color=red, label="'char' -> 'int'"]
- "20" -> "22" [label=""]
- "19" -> "20" [label=""]
+ "19" [color=red, label="added(const int struct S::* volatile s9)"]
"0" -> "19" [label=""]
+ "20" [label="'char struct A::* diff' -> 'int struct B::* diff'"]
+ "21" [label="'char struct A::*' -> 'int struct B::*'"]
+ "22" [color=red, label="'struct A' -> 'struct B'"]
+ "21" -> "22" [label="containing"]
+ "23" [color=red, label="'char' -> 'int'"]
+ "21" -> "23" [label=""]
+ "20" -> "21" [label=""]
+ "0" -> "20" [label=""]
}
diff --git a/test_cases/diff_tests/member/pointer_to_member.1.cc b/test_cases/diff_tests/member/pointer_to_member.1.cc
index 61011ee..9779061 100644
--- a/test_cases/diff_tests/member/pointer_to_member.1.cc
+++ b/test_cases/diff_tests/member/pointer_to_member.1.cc
@@ -21,6 +21,9 @@ int (S::*s7)();
int (S::*s8)[7];
// declare s9 as volatile pointer to member of class S const int
const int S::* volatile s9;
+// declare s10 as function (pointer to member of class S int) returning int
+int s10(int S::*);
+int s10(int S::*) { return 0; }
struct X {
void f(int);
@@ -48,8 +51,6 @@ auto pmu = &U::u;
typedef const U CU;
auto pmcu = &CU::u;
-// TODO: everything above here should be an info test
-
struct B {
int x;
};
diff --git a/test_cases/info_tests/member/expected/pointer_to_member_cc.elf_stg b/test_cases/info_tests/member/expected/pointer_to_member_cc.elf_stg
index 7b197b6..6d9e1d4 100644
--- a/test_cases/info_tests/member/expected/pointer_to_member_cc.elf_stg
+++ b/test_cases/info_tests/member/expected/pointer_to_member_cc.elf_stg
@@ -206,6 +206,11 @@ function {
id: 0x9d80e32f
return_type_id: 0x6720d32f
}
+function {
+ id: 0xa875fb6e
+ return_type_id: 0x6720d32f
+ parameter_id: 0xd7d46104
+}
elf_symbol {
id: 0xba0e5cd0
name: "_Z2s2v"
@@ -215,6 +220,14 @@ elf_symbol {
full_name: "s2"
}
elf_symbol {
+ id: 0x94e5eb64
+ name: "_Z3s10M1Si"
+ is_defined: true
+ symbol_type: FUNCTION
+ type_id: 0xa875fb6e
+ full_name: "s10"
+}
+elf_symbol {
id: 0x13e4cc52
name: "_Z7pmz_funv"
is_defined: true
@@ -353,6 +366,7 @@ elf_symbol {
interface {
id: 0x84ea5130
symbol_id: 0xba0e5cd0
+ symbol_id: 0x94e5eb64
symbol_id: 0x13e4cc52
symbol_id: 0x648621f2
symbol_id: 0xff819903
diff --git a/test_cases/info_tests/member/pointer_to_member.cc b/test_cases/info_tests/member/pointer_to_member.cc
index 5e5321c..20f9dcb 100644
--- a/test_cases/info_tests/member/pointer_to_member.cc
+++ b/test_cases/info_tests/member/pointer_to_member.cc
@@ -21,6 +21,9 @@ int (S::*s7)();
int (S::*s8)[7];
// declare s9 as volatile pointer to member of class S const int
const int S::* volatile s9;
+// declare s10 as function (pointer to member of class S int) returning int
+int s10(int S::*);
+int s10(int S::*) { return 0; }
struct X {
void f(int);
diff --git a/test_cases/info_tests/source_filter/expected/type_roots_cc.elf_stg b/test_cases/info_tests/source_filter/expected/type_roots_cc.elf_stg
new file mode 100644
index 0000000..e91b30c
--- /dev/null
+++ b/test_cases/info_tests/source_filter/expected/type_roots_cc.elf_stg
@@ -0,0 +1,5 @@
+version: 0x00000002
+root_id: 0x84ea5130
+interface {
+ id: 0x84ea5130
+}
diff --git a/test_cases/info_tests/source_filter/expected/composite_and_enum_cc.elf_stg b/test_cases/info_tests/source_filter/expected/types_cc.elf_stg
index 4ec229b..f6c669d 100644
--- a/test_cases/info_tests/source_filter/expected/composite_and_enum_cc.elf_stg
+++ b/test_cases/info_tests/source_filter/expected/types_cc.elf_stg
@@ -1,5 +1,19 @@
version: 0x00000002
root_id: 0x84ea5130
+special {
+ id: 0x48b5725f
+ kind: VOID
+}
+pointer_reference {
+ id: 0x18bd6530
+ kind: POINTER
+ pointee_type_id: 0x48b5725f
+}
+typedef {
+ id: 0x4f137329
+ name: "Typedef"
+ referred_type_id: 0x18bd6530
+}
struct_union {
id: 0x54a61673
kind: STRUCT
@@ -56,6 +70,14 @@ elf_symbol {
full_name: "foo_struct"
}
elf_symbol {
+ id: 0x90772e58
+ name: "foo_typedef"
+ is_defined: true
+ symbol_type: OBJECT
+ type_id: 0x4f137329
+ full_name: "foo_typedef"
+}
+elf_symbol {
id: 0xc77e6f56
name: "foo_union"
is_defined: true
@@ -69,5 +91,6 @@ interface {
symbol_id: 0x5f43725e
symbol_id: 0x49093003
symbol_id: 0x8361f42b
+ symbol_id: 0x90772e58
symbol_id: 0xc77e6f56
}
diff --git a/test_cases/info_tests/source_filter/composite_and_enum.cc b/test_cases/info_tests/source_filter/type_roots.cc
index b73bcb0..5d393dd 100644
--- a/test_cases/info_tests/source_filter/composite_and_enum.cc
+++ b/test_cases/info_tests/source_filter/type_roots.cc
@@ -20,8 +20,11 @@ enum class EnumClass {
ONE = 1,
};
+typedef void* Typedef;
+
Struct foo_struct;
Union foo_union;
Class foo_class;
Enum foo_enum;
EnumClass foo_enum_class;
+Typedef foo_typedef;
diff --git a/test_cases/info_tests/source_filter/types.cc b/test_cases/info_tests/source_filter/types.cc
new file mode 100644
index 0000000..5d393dd
--- /dev/null
+++ b/test_cases/info_tests/source_filter/types.cc
@@ -0,0 +1,30 @@
+struct Struct {
+ long x;
+};
+
+union Union {
+ long y;
+};
+
+class Class {
+ long z;
+};
+
+enum Enum {
+ ENUM_ZERO = 0,
+ ENUM_ONE = 1,
+};
+
+enum class EnumClass {
+ ZERO = 0,
+ ONE = 1,
+};
+
+typedef void* Typedef;
+
+Struct foo_struct;
+Union foo_union;
+Class foo_class;
+Enum foo_enum;
+EnumClass foo_enum_class;
+Typedef foo_typedef;
diff --git a/test_cases/info_tests/symbol/expected/tls_emulated_c.elf_stg b/test_cases/info_tests/symbol/expected/tls_emulated_c.elf_stg
new file mode 100644
index 0000000..b4cd4f9
--- /dev/null
+++ b/test_cases/info_tests/symbol/expected/tls_emulated_c.elf_stg
@@ -0,0 +1,26 @@
+version: 0x00000002
+root_id: 0x84ea5130
+elf_symbol {
+ id: 0x688c97e0
+ name: "__emutls_t.var2"
+ is_defined: true
+ symbol_type: OBJECT
+}
+elf_symbol {
+ id: 0xa2dcdaef
+ name: "__emutls_v.var1"
+ is_defined: true
+ symbol_type: OBJECT
+}
+elf_symbol {
+ id: 0xe19c7b87
+ name: "__emutls_v.var2"
+ is_defined: true
+ symbol_type: OBJECT
+}
+interface {
+ id: 0x84ea5130
+ symbol_id: 0x688c97e0
+ symbol_id: 0xa2dcdaef
+ symbol_id: 0xe19c7b87
+}
diff --git a/test_cases/info_tests/symbol/expected/tls_emulated_cc.elf_stg b/test_cases/info_tests/symbol/expected/tls_emulated_cc.elf_stg
new file mode 100644
index 0000000..3ddf217
--- /dev/null
+++ b/test_cases/info_tests/symbol/expected/tls_emulated_cc.elf_stg
@@ -0,0 +1,38 @@
+version: 0x00000002
+root_id: 0x84ea5130
+primitive {
+ id: 0x6720d32f
+ name: "int"
+ encoding: SIGNED_INTEGER
+ bytesize: 0x00000004
+}
+function {
+ id: 0x9d80e32f
+ return_type_id: 0x6720d32f
+}
+elf_symbol {
+ id: 0x92009dc1
+ name: "_Z3barv"
+ is_defined: true
+ symbol_type: FUNCTION
+ type_id: 0x9d80e32f
+ full_name: "bar"
+}
+elf_symbol {
+ id: 0x6c57e66c
+ name: "__emutls_v._ZN2ns3fooE"
+ is_defined: true
+ symbol_type: OBJECT
+}
+elf_symbol {
+ id: 0xb0192ccb
+ name: "__emutls_v.foo"
+ is_defined: true
+ symbol_type: OBJECT
+}
+interface {
+ id: 0x84ea5130
+ symbol_id: 0x92009dc1
+ symbol_id: 0x6c57e66c
+ symbol_id: 0xb0192ccb
+}
diff --git a/test_cases/info_tests/symbol/expected/version_definition_c.elf_stg b/test_cases/info_tests/symbol/expected/version_definition_c.elf_stg
index e9e0b9b..6342898 100644
--- a/test_cases/info_tests/symbol/expected/version_definition_c.elf_stg
+++ b/test_cases/info_tests/symbol/expected/version_definition_c.elf_stg
@@ -32,7 +32,7 @@ elf_symbol {
is_defined: true
symbol_type: FUNCTION
type_id: 0x10985193
- full_name: "versioned_foo_v1"
+ full_name: "versioned_foo"
}
elf_symbol {
id: 0xc828cd97
diff --git a/test_cases/info_tests/symbol/version_definition.c b/test_cases/info_tests/symbol/version_definition.c
index 0127d57..af87429 100644
--- a/test_cases/info_tests/symbol/version_definition.c
+++ b/test_cases/info_tests/symbol/version_definition.c
@@ -6,14 +6,16 @@
void tweak(int dummy);
+void versioned_foo(void) { tweak(1); }
+
__asm__(".symver versioned_foo_v1, versioned_foo@@VERS_1");
-void versioned_foo_v1(void) { tweak(1); }
+void versioned_foo_v1(void) { tweak(2); }
__asm__(".symver versioned_foo_v2, versioned_foo@VERS_2");
-void versioned_foo_v2(void) { tweak(2); }
+void versioned_foo_v2(void) { tweak(3); }
__asm__(".symver versioned_foo_v3, versioned_foo@VERS_3");
-void versioned_foo_v3(void) { tweak(3); }
+void versioned_foo_v3(void) { tweak(4); }
// Using a libc function helps to add the "version needs" section
// in addition to the "version definitions". This helps to catch