forked from google/centipede
-
Notifications
You must be signed in to change notification settings - Fork 0
/
symbol_table.cc
104 lines (95 loc) · 3.51 KB
/
symbol_table.cc
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
// Copyright 2022 The Centipede Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "./symbol_table.h"
#include <cstdlib>
#include <filesystem>
#include <fstream>
#include <string>
#include <string_view>
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "./command.h"
#include "./coverage.h"
#include "./logging.h"
#include "./util.h"
namespace centipede {
void SymbolTable::ReadFromLLVMSymbolizer(std::istream &in) {
// We remove some useless file prefixes for better human readability.
const std::string file_prefixes_to_remove[] = {"/proc/self/cwd/", "./"};
while (in) {
// We (mostly) blindly trust the input format is correct.
std::string func, file, empty;
std::getline(in, func);
std::getline(in, file);
std::getline(in, empty);
CHECK(empty.empty());
if (!in) break;
for (auto &bad_prefix : file_prefixes_to_remove) {
if (absl::StartsWith(file, bad_prefix)) {
file = file.substr(bad_prefix.size());
}
}
AddEntry(func, file);
}
}
void SymbolTable::GetSymbolsFromBinary(const Coverage::PCTable &pc_table,
std::string_view binary_path,
std::string_view symbolizer_path,
std::string_view tmp_path1,
std::string_view tmp_path2) {
// NOTE: --symbolizer_path=/dev/null is a somewhat expected alternative to ""
// that users might pass.
if (symbolizer_path.empty() || symbolizer_path == "/dev/null") {
LOG(WARNING) << "Symbolizer unspecified: debug symbols will not be used";
} else {
auto pcs_path(tmp_path1);
auto symbols_path(tmp_path2);
// Create the input file (one PC per line).
std::string pcs_string;
for (auto &pc_info : pc_table) {
absl::StrAppend(&pcs_string, "0x", absl::Hex(pc_info.pc), "\n");
}
WriteToLocalFile(pcs_path, pcs_string);
// Run the symbolizer.
Command cmd(symbolizer_path,
{"--no-inlines", "-e", std::string(binary_path), "<",
std::string(pcs_path)},
{/*env*/}, symbols_path);
int exit_code = cmd.Execute();
if (exit_code != EXIT_SUCCESS) {
LOG(ERROR) << "system() failed: " << VV(cmd.ToString()) << VV(exit_code);
} else {
// Get and process the symbolizer output.
std::ifstream symbolizer_output(std::string{symbols_path});
ReadFromLLVMSymbolizer(symbolizer_output);
std::filesystem::remove(pcs_path);
std::filesystem::remove(symbols_path);
if (size() != pc_table.size()) {
LOG(ERROR) << "Symbolization failed: debug symbols will not be used";
}
}
}
if (size() != pc_table.size()) {
// Something went wrong. Set symbols to unknown so the sizes of pc_table and
// symbols always match.
SetAllToUnknown(pc_table.size());
}
}
void SymbolTable::SetAllToUnknown(size_t size) {
entries_.resize(size);
for (auto &entry : entries_) {
entry = {"?", "?"};
}
}
} // namespace centipede