File: test-read-btf.cc

package info (click to toggle)
libabigail 2.9-2
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 1,021,756 kB
  • sloc: xml: 572,663; cpp: 110,945; sh: 11,868; ansic: 4,329; makefile: 3,486; python: 1,684; ada: 62
file content (188 lines) | stat: -rw-r--r-- 5,157 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
// -*- Mode: C++ -*-
//
// Copyright (C) 2022-2025 Red Hat, Inc.
//
// Author: Dodji Seketeli

/// @file
///
/// This file is part of the BTF testsuite. It reads ELF binaries
/// containing BTF, save them in XML corpus files and diff the
/// corpus files against reference XML corpus files.

#include <cstdlib>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "abg-btf-reader.h"
#include "test-read-common.h"

using std::string;
using std::cerr;
using std::vector;

using abigail::tests::read_common::InOutSpec;
using abigail::tests::read_common::test_task;
using abigail::tests::read_common::display_usage;
using abigail::tests::read_common::options;

using abigail::btf::create_reader;
using abigail::xml_writer::SEQUENCE_TYPE_ID_STYLE;
using abigail::xml_writer::HASH_TYPE_ID_STYLE;
using abigail::tools_utils::emit_prefix;

static InOutSpec in_out_specs[] =
{
  {
    "data/test-read-btf/test0.o",
    "",
    "",
    SEQUENCE_TYPE_ID_STYLE,
    "data/test-read-btf/test0.o.abi",
    "output/test-read-btf/test0.o.abi",
    "--btf",
  },
  {
    "data/test-read-btf/test1.o",
    "",
    "",
    SEQUENCE_TYPE_ID_STYLE,
    "data/test-read-btf/test1.o.abi",
    "output/test-read-btf/test1.o.abi",
    "--btf",
  },
  // This should be the last entry.
  {NULL, NULL, NULL, SEQUENCE_TYPE_ID_STYLE, NULL, NULL, NULL}
};

/// Task specialization to perform BTF tests.
struct test_task_btf : public test_task
{
  test_task_btf(const InOutSpec &s,
                string& a_out_abi_base,
                string& a_in_elf_base,
                string& a_in_abi_base);
  virtual void
  perform();

  virtual
  ~test_task_btf()
  {}
}; // end struct test_task_btf

/// Constructor.
///
/// Task to be executed for each BTF test entry in @ref
/// abigail::tests::read_common::InOutSpec.
/// @param InOutSpec the array containing set of tests.
///
/// @param a_out_abi_base the output base directory for abixml files.
///
/// @param a_in_elf_base the input base directory for object files.
///
/// @param a_in_elf_base the input base directory for expected
/// abixml files.
test_task_btf::test_task_btf(const InOutSpec &s,
                             string& a_out_abi_base,
                             string& a_in_elf_base,
                             string& a_in_abi_base)
        : test_task(s, a_out_abi_base, a_in_elf_base, a_in_abi_base)
  {}

/// The thread function to execute each BTF test entry in @ref
/// abigail::tests::read_common::InOutSpec.
///
/// This reads the corpus into memory, saves it to disk, loads it
/// again and compares the new in-memory representation against the
void
test_task_btf::perform()
{
  abigail::ir::environment env;

  set_in_elf_path();
  set_in_suppr_spec_path();

  abigail::fe_iface::status status =
    abigail::fe_iface::STATUS_UNKNOWN;
  vector<string> di_roots;
  ABG_ASSERT(abigail::tools_utils::file_exists(in_elf_path));

  abigail::elf_based_reader_sptr rdr = abigail::btf::create_reader(in_elf_path,
								   di_roots, env);
  ABG_ASSERT(rdr);

  corpus_sptr corp = rdr->read_corpus(status);

  // if there is no output and no input, assume that we do not care about the
  // actual read result, just that it succeeded.
  if (!spec.in_abi_path && !spec.out_abi_path)
    {
        // Phew! we made it here and we did not crash! yay!
        return;
    }
  if (!corp)
    {
        error_message = string("failed to read ") + in_elf_path  + "\n";
        is_ok = false;
        return;
    }
  corp->set_path(spec.in_elf_path);
  // Do not take architecture names in comparison so that these
  // test input binaries can come from whatever arch the
  // programmer likes.
  corp->set_architecture_name("");

  if (!(is_ok = set_out_abi_path()))
      return;

  if (!(is_ok = serialize_corpus(out_abi_path, corp)))
       return;

  if (!(is_ok = run_abidw("--btf ")))
    return;

  if (!(is_ok = run_diff()))
      return;
}

/// Create a new BTF instance for task to be execute by the testsuite.
///
/// @param s the @ref abigail::tests::read_common::InOutSpec
/// tests container.
///
/// @param a_out_abi_base the output base directory for abixml files.
///
/// @param a_in_elf_base the input base directory for object files.
///
/// @param a_in_abi_base the input base directory for abixml files.
///
/// @return abigail::tests::read_common::test_task instance.
static test_task*
new_task(const InOutSpec* s, string& a_out_abi_base,
         string& a_in_elf_base, string& a_in_abi_base)
{
  return new test_task_btf(*s, a_out_abi_base,
                           a_in_elf_base, a_in_abi_base);
}

int
main(int argc, char *argv[])
{
  options opts;
  if (!parse_command_line(argc, argv, opts))
    {
      if (!opts.wrong_option.empty())
        emit_prefix(argv[0], cerr)
          << "unrecognized option: " << opts.wrong_option << "\n";
      display_usage(argv[0], cerr);
      return 1;
    }

  // compute number of tests to be executed.
  const size_t num_tests = sizeof(in_out_specs) / sizeof(InOutSpec) - 1;

  return run_tests(num_tests, in_out_specs, opts, new_task);
}