Skip to content

Commit a92ca1c

Browse files
committed
Update GoOffsetTracker to use correct version key for a given module
Signed-off-by: Dom Del Nano <ddelnano@gmail.com>
1 parent 605915d commit a92ca1c

3 files changed

Lines changed: 94 additions & 58 deletions

File tree

src/stirling/source_connectors/socket_tracer/uprobe_manager.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -903,8 +903,10 @@ int UProbeManager::DeployGoUProbes(const absl::flat_hash_set<md::UPID>& pids) {
903903
}
904904

905905
std::unique_ptr<DwarfReader> dwarf_reader = dwarf_reader_status.ConsumeValueOrDie();
906-
std::unique_ptr<GoOffsetLocator> offset_locator =
907-
std::make_unique<GoOffsetLocator>(dwarf_reader.get(), build_info, go_version);
906+
StructOffsetMap struct_offsets;
907+
FunctionArgMap function_offsets;
908+
std::unique_ptr<GoOffsetLocator> offset_locator = std::make_unique<GoOffsetLocator>(
909+
dwarf_reader.get(), struct_offsets, function_offsets, build_info, go_version);
908910
Status s = UpdateGoCommonSymAddrs(elf_reader.get(), offset_locator.get(), pid_vec);
909911
if (!s.ok()) {
910912
VLOG(1) << absl::Substitute(

src/stirling/source_connectors/socket_tracer/uprobe_symaddrs.h

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <map>
2222
#include <memory>
2323
#include <string>
24+
#include <utility>
2425

2526
#include "src/common/base/base.h"
2627
#include "src/stirling/obj_tools/dwarf_reader.h"
@@ -39,21 +40,14 @@ namespace stirling {
3940

4041
constexpr std::string_view kLibNettyTcnativePrefix = "libnetty_tcnative_linux_x86";
4142

42-
using StructOffsetMap =
43-
std::map<std::string, std::map<std::string, std::map<std::string, int32_t>>>;
44-
using FunctionArgMap =
45-
std::map<std::string,
46-
std::map<std::string, std::map<std::string, std::unique_ptr<obj_tools::VarLocation>>>>;
43+
using StructVersionMap = std::map<std::string, std::map<std::string, int32_t>>;
44+
using StructOffsetMap = std::map<std::string, std::pair<std::string, StructVersionMap>>;
45+
using FuncVersionMap =
46+
std::map<std::string, std::map<std::string, std::unique_ptr<obj_tools::VarLocation>>>;
47+
using FunctionArgMap = std::map<std::string, std::pair<std::string, FuncVersionMap>>;
4748

4849
class GoOffsetLocator {
4950
public:
50-
// TODO(ddelnano): Remove this constructor once the scaffolding to populate StructOffsetMap
51-
// and FunctionArgMap is available.
52-
GoOffsetLocator(obj_tools::DwarfReader* dwarf_reader, const obj_tools::BuildInfo& build_info,
53-
const std::string& go_version)
54-
: GoOffsetLocator(dwarf_reader, StructOffsetMap{}, FunctionArgMap{}, build_info, go_version) {
55-
}
56-
5751
GoOffsetLocator(obj_tools::DwarfReader* dwarf_reader, const StructOffsetMap& struct_offsets,
5852
const FunctionArgMap& function_args, const obj_tools::BuildInfo& build_info,
5953
const std::string& go_version)
@@ -87,18 +81,20 @@ class GoOffsetLocator {
8781
return GetStructMemberOffsetFromOffsets(struct_name, member_name);
8882
}
8983

90-
const std::string& go_version() const { return go_version_; }
84+
std::string go_version() const { return go_version_; }
9185

9286
private:
9387
StatusOr<std::map<std::string, obj_tools::ArgInfo>> GetFunctionArgInfoFromOffsets(
9488
std::string_view function_symbol_name) {
95-
auto fn_map = function_args_.find(std::string(function_symbol_name));
96-
if (fn_map == function_args_.end()) {
89+
auto fn_map_pair = function_args_.find(std::string(function_symbol_name));
90+
if (fn_map_pair == function_args_.end()) {
9791
return error::Internal("Unable to find function location for $0", function_symbol_name);
9892
}
93+
auto& [mod_name, fn_map] = fn_map_pair->second;
94+
std::string version_key = mod_version_map_[mod_name];
9995
std::map<std::string, obj_tools::ArgInfo> result;
100-
for (const auto& [arg_name, version_info_map] : fn_map->second) {
101-
std::string version_key = go_version_;
96+
97+
for (const auto& [arg_name, version_info_map] : fn_map) {
10298
auto version_map = version_info_map.find(version_key);
10399
if (version_map == version_info_map.end()) {
104100
return error::Internal("Unable to find function location for arg=$0 version=$1", arg_name,
@@ -116,17 +112,18 @@ class GoOffsetLocator {
116112

117113
StatusOr<uint64_t> GetStructMemberOffsetFromOffsets(std::string_view struct_name,
118114
std::string_view member_name) {
119-
auto struct_map = struct_offsets_.find(std::string(struct_name));
120-
if (struct_map == struct_offsets_.end()) {
115+
auto struct_map_pair = struct_offsets_.find(std::string(struct_name));
116+
if (struct_map_pair == struct_offsets_.end()) {
121117
return error::Internal("Unable to find offsets for struct=$0", struct_name);
122118
}
123-
auto member_map = struct_map->second.find(std::string(member_name));
124-
if (member_map == struct_map->second.end()) {
119+
auto& [mod_name, struct_map] = struct_map_pair->second;
120+
auto member_map = struct_map.find(std::string(member_name));
121+
if (member_map == struct_map.end()) {
125122
return error::Internal("Unable to find offsets for struct member=$0.$1", struct_name,
126123
member_name);
127124
}
128125

129-
std::string version_key = go_version_;
126+
std::string version_key = mod_version_map_[mod_name];
130127
auto version_map = member_map->second.find(version_key);
131128
if (version_map == member_map->second.end()) {
132129
return error::Internal("Unable to find offsets for struct member=$0.$1 for version $2",
@@ -138,14 +135,12 @@ class GoOffsetLocator {
138135
void PopulateModuleVersions(const obj_tools::BuildInfo& build_info) {
139136
for (const auto& dep : build_info.deps) {
140137
// Find the related dependencies and strip the "v" prefix
141-
if (dep.path == "golang.org/x/net") {
142-
golang_x_net_version_ = dep.version.substr(1);
143-
} else if (dep.path == "google.golang.org/grpc") {
144-
google_golang_grpc_version_ = dep.version.substr(1);
138+
if (dep.path == "golang.org/x/net" || dep.path == "google.golang.org/grpc") {
139+
VLOG(1) << absl::Substitute("Found dependency: $0, version: $1", dep.path, dep.version);
140+
mod_version_map_[dep.path] = dep.version.substr(1);
145141
}
146142
}
147-
VLOG(1) << "golang.org/x/net module version: " << golang_x_net_version_;
148-
VLOG(1) << "google.golang.org/grpc module version: " << google_golang_grpc_version_;
143+
mod_version_map_["std"] = go_version_;
149144
}
150145

151146
obj_tools::DwarfReader* dwarf_reader_;
@@ -155,8 +150,7 @@ class GoOffsetLocator {
155150

156151
const std::string& go_version_;
157152

158-
std::string golang_x_net_version_;
159-
std::string google_golang_grpc_version_;
153+
std::map<std::string, std::string> mod_version_map_;
160154
};
161155

162156
/**

src/stirling/source_connectors/socket_tracer/uprobe_symaddrs_test.cc

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ class UprobeSymaddrsTest : public ::testing::Test {
4040
void SetUp() {
4141
std::filesystem::path p = px::testing::BazelRunfilePath(kGoGRPCServer);
4242
ASSERT_OK_AND_ASSIGN(dwarf_reader_, DwarfReader::CreateIndexingAll(p));
43-
offset_locator_ = std::make_unique<GoOffsetLocator>(
44-
GoOffsetLocator(dwarf_reader_.get(), {}, {}, {}, "1.19.0"));
43+
offset_locator_ = std::make_unique<GoOffsetLocator>(GoOffsetLocator(
44+
dwarf_reader_.get(), struct_offsets_, function_args_, build_info_, "1.19.0"));
4545
ASSERT_OK_AND_ASSIGN(elf_reader_, ElfReader::Create(p));
4646
}
4747

@@ -50,6 +50,9 @@ class UprobeSymaddrsTest : public ::testing::Test {
5050

5151
std::unique_ptr<DwarfReader> dwarf_reader_;
5252
std::unique_ptr<GoOffsetLocator> offset_locator_;
53+
StructOffsetMap struct_offsets_;
54+
FunctionArgMap function_args_;
55+
obj_tools::BuildInfo build_info_;
5356
std::unique_ptr<ElfReader> elf_reader_;
5457
};
5558

@@ -112,59 +115,98 @@ TEST(UprobeSymaddrsNodeTest, TLSWrapSymAddrsFromDwarfInfo) {
112115
EXPECT_EQ(symaddrs.uv__io_s_fd_offset, 0x04);
113116
}
114117

118+
StructOffsetMap empty_struct_map;
119+
FunctionArgMap empty_fn_arg_map;
120+
obj_tools::BuildInfo empty_build_info;
121+
115122
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFMissingStruct) {
116-
auto offset_locator = GoOffsetLocator(nullptr, {}, {}, {}, "");
123+
auto offset_locator =
124+
GoOffsetLocator(nullptr, empty_struct_map, empty_fn_arg_map, empty_build_info, "");
117125
auto status = offset_locator.GetStructMemberOffset("runtime.g", "goid");
118126
EXPECT_FALSE(status.ok());
119127
}
120128

121129
// NOLINTNEXTLINE: runtime/string
122130
std::string go_version = "1.19.0";
123-
auto struct_map = StructOffsetMap{{"runtime.g", {{"goid", {{go_version, 152}}}}}};
131+
// NOLINTNEXTLINE: runtime/string
132+
std::string golang_x_net_version = "v1.0.0";
133+
134+
auto struct_map = StructOffsetMap{
135+
{
136+
"runtime.g",
137+
{"std", {{"goid", {{go_version, 152}}}}},
138+
},
139+
{
140+
"golang.org/x/net/http2.DataFrame",
141+
{"golang.org/x/net", {{"data", {{golang_x_net_version.substr(1), 16}}}}},
142+
},
143+
};
124144

125145
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFMissingMember) {
126-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, {}, {}, go_version);
146+
auto offset_locator =
147+
GoOffsetLocator(nullptr, struct_map, empty_fn_arg_map, empty_build_info, go_version);
127148
EXPECT_FALSE(offset_locator.GetStructMemberOffset("runtime.g", "missing_member").ok());
128149
}
129150

130151
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFMissingVersion) {
131-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, {}, {}, "1.18.0");
152+
auto offset_locator =
153+
GoOffsetLocator(nullptr, struct_map, empty_fn_arg_map, empty_build_info, "1.18.0");
132154
EXPECT_FALSE(offset_locator.GetStructMemberOffset("runtime.g", "goid").ok());
133155
}
134156

135-
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFSuccessfulLookup) {
136-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, {}, {}, go_version);
157+
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFSuccessfulLookupStdlib) {
158+
auto offset_locator =
159+
GoOffsetLocator(nullptr, struct_map, empty_fn_arg_map, empty_build_info, go_version);
137160

138161
ASSERT_OK_AND_ASSIGN(uint64_t offset, offset_locator.GetStructMemberOffset("runtime.g", "goid"));
139162
EXPECT_EQ(offset, 152);
140163
}
141164

165+
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFSuccessfulLookupGolangXNet) {
166+
obj_tools::BuildInfo build_info;
167+
build_info.deps.push_back(
168+
obj_tools::Module{"golang.org/x/net", golang_x_net_version, "", nullptr});
169+
auto offset_locator =
170+
GoOffsetLocator(nullptr, struct_map, empty_fn_arg_map, build_info, go_version);
171+
172+
ASSERT_OK_AND_ASSIGN(uint64_t offset, offset_locator.GetStructMemberOffset(
173+
"golang.org/x/net/http2.DataFrame", "data"));
174+
EXPECT_EQ(offset, 16);
175+
}
176+
142177
TEST(GoOffsetLocator, GetFunctionArgInfoNoDWARFMissingFunction) {
143-
auto offset_locator = GoOffsetLocator(nullptr, {}, {}, {}, "");
178+
auto offset_locator =
179+
GoOffsetLocator(nullptr, empty_struct_map, empty_fn_arg_map, empty_build_info, go_version);
144180
auto status = offset_locator.GetFunctionArgInfo("missing_func");
145181
EXPECT_FALSE(status.ok());
146182
}
147183

148-
TEST(GoOffsetLocator, GetFunctionArgInfoNoDWARFMissingVersion) {
149-
FunctionArgMap fn_arg_map;
184+
FunctionArgMap GetFunctionArgMap() {
150185
auto var_location = obj_tools::VarLocation{obj_tools::LocationType::kRegister, 8};
151-
fn_arg_map["crypto/tls.(*Conn).Read"]["b"][go_version] =
186+
FunctionArgMap fn_arg_map;
187+
fn_arg_map["crypto/tls.(*Conn).Read"] = std::make_pair("std", FuncVersionMap{});
188+
fn_arg_map["crypto/tls.(*Conn).Read"].second["b"][go_version] =
152189
std::make_unique<obj_tools::VarLocation>(var_location);
190+
return fn_arg_map;
191+
}
153192

154-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, fn_arg_map, {}, "1.18.0");
193+
TEST(GoOffsetLocator, GetFunctionArgInfoNoDWARFMissingVersion) {
194+
FunctionArgMap fn_arg_map = GetFunctionArgMap();
195+
auto offset_locator =
196+
GoOffsetLocator(nullptr, struct_map, fn_arg_map, empty_build_info, "1.18.0");
155197
auto status = offset_locator.GetFunctionArgInfo("crypto/tls.(*Conn).Write");
156198
EXPECT_FALSE(status.ok());
157199
}
158200

159201
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFUnknownLocation) {
160-
FunctionArgMap fn_arg_map;
161202
auto var_location = obj_tools::VarLocation{obj_tools::LocationType::kUnknown, -1};
162-
fn_arg_map["crypto/tls.(*Conn).Read"]["b"][go_version] =
203+
auto fn_arg_map = GetFunctionArgMap();
204+
fn_arg_map["crypto/tls.(*Conn).Read"].second["b"][go_version] =
163205
std::make_unique<obj_tools::VarLocation>(var_location);
164206

165-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, fn_arg_map, {}, go_version);
207+
auto offset_locator =
208+
GoOffsetLocator(nullptr, struct_map, fn_arg_map, empty_build_info, go_version);
166209

167-
auto status = offset_locator.GetFunctionArgInfo("crypto/tls.(*Conn).Read");
168210
ASSERT_OK_AND_ASSIGN(auto args, offset_locator.GetFunctionArgInfo("crypto/tls.(*Conn).Read"));
169211
EXPECT_NE(args.find("b"), args.end());
170212
auto& arg_info = args["b"];
@@ -173,22 +215,20 @@ TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFUnknownLocation) {
173215
}
174216

175217
TEST(GoOffsetLocator, GetStructMemberOffsetNoDWARFNullLocation) {
176-
FunctionArgMap fn_arg_map;
177-
fn_arg_map["crypto/tls.(*Conn).Read"]["b"][go_version] = nullptr;
218+
FunctionArgMap fn_arg_map = GetFunctionArgMap();
219+
fn_arg_map["crypto/tls.(*Conn).Read"].second["b"][go_version] = nullptr;
178220

179-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, fn_arg_map, {}, go_version);
221+
auto offset_locator =
222+
GoOffsetLocator(nullptr, struct_map, fn_arg_map, empty_build_info, go_version);
180223

181224
auto status = offset_locator.GetFunctionArgInfo("crypto/tls.(*Conn).Read");
182225
EXPECT_FALSE(status.ok());
183226
}
184227

185228
TEST(GoOffsetLocator, GetFunctionArgInfoNoDWARFSuccessfulLookup) {
186-
FunctionArgMap fn_arg_map;
187-
auto var_location = obj_tools::VarLocation{obj_tools::LocationType::kRegister, 8};
188-
fn_arg_map["crypto/tls.(*Conn).Read"]["b"][go_version] =
189-
std::make_unique<obj_tools::VarLocation>(var_location);
190-
191-
auto offset_locator = GoOffsetLocator(nullptr, struct_map, fn_arg_map, {}, go_version);
229+
FunctionArgMap fn_arg_map = GetFunctionArgMap();
230+
auto offset_locator =
231+
GoOffsetLocator(nullptr, struct_map, fn_arg_map, empty_build_info, go_version);
192232

193233
ASSERT_OK_AND_ASSIGN(auto args, offset_locator.GetFunctionArgInfo("crypto/tls.(*Conn).Read"));
194234
EXPECT_NE(args.find("b"), args.end());

0 commit comments

Comments
 (0)