blob: c17a4663346d8a714af0ddc96c09080c582c35a2 [file] [log] [blame]
Vicent Marti0865f942016-04-27 16:57:58 +02001/*
2 * Copyright (c) 2016 GitHub, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Teng Qin488c1192017-09-13 10:47:59 -070016#include <algorithm>
Vicent Martieca47832016-05-01 12:53:46 +020017#include <cstring>
Vicent Marti1a2ddac2016-05-01 13:41:33 +020018#include <sstream>
Yonghong Song0ba15072017-07-21 22:13:20 -070019#include <unordered_set>
Vicent Marti0865f942016-04-27 16:57:58 +020020
Vicent Marti92598412016-04-28 19:42:55 +020021#include <fcntl.h>
22#include <sys/types.h>
23#include <unistd.h>
24
Vicent Marti0865f942016-04-27 16:57:58 +020025#include "bcc_elf.h"
Vicent Marti92598412016-04-28 19:42:55 +020026#include "bcc_proc.h"
Vicent Marti0865f942016-04-27 16:57:58 +020027#include "usdt.h"
28#include "vendor/tinyformat.hpp"
Sasha Goldshtein69e361a2016-09-27 19:40:00 +030029#include "bcc_usdt.h"
Vicent Marti0865f942016-04-27 16:57:58 +020030
31namespace USDT {
32
Sasha Goldshtein6e91a742016-10-06 18:18:18 +030033Location::Location(uint64_t addr, const char *arg_fmt) : address_(addr) {
Vicent Marti0865f942016-04-27 16:57:58 +020034 ArgumentParser_x64 parser(arg_fmt);
35 while (!parser.done()) {
Vicent Martieca47832016-05-01 12:53:46 +020036 Argument arg;
37 if (!parser.parse(&arg))
Vicent Marti0865f942016-04-27 16:57:58 +020038 continue;
Vicent Martieca47832016-05-01 12:53:46 +020039 arguments_.push_back(std::move(arg));
Vicent Marti0865f942016-04-27 16:57:58 +020040 }
41}
42
43Probe::Probe(const char *bin_path, const char *provider, const char *name,
Vicent Marti96c1b8e2017-06-27 19:06:46 +020044 uint64_t semaphore, const optional<int> &pid, ProcMountNS *ns)
Vicent Marti0865f942016-04-27 16:57:58 +020045 : bin_path_(bin_path),
46 provider_(provider),
47 name_(name),
Vicent Marti10436452016-05-04 16:58:51 +020048 semaphore_(semaphore),
Vicent Marti96c1b8e2017-06-27 19:06:46 +020049 pid_(pid),
50 mount_ns_(ns) {}
Vicent Marti0865f942016-04-27 16:57:58 +020051
Vicent Marti92598412016-04-28 19:42:55 +020052bool Probe::in_shared_object() {
Vicent Marti96c1b8e2017-06-27 19:06:46 +020053 if (!in_shared_object_) {
54 ProcMountNSGuard g(mount_ns_);
Teng Qind82e8132017-05-04 12:09:14 -070055 in_shared_object_ = bcc_elf_is_shared_obj(bin_path_.c_str());
Vicent Marti96c1b8e2017-06-27 19:06:46 +020056 }
Vicent Marti92598412016-04-28 19:42:55 +020057 return in_shared_object_.value();
58}
59
Vicent Marti10436452016-05-04 16:58:51 +020060bool Probe::resolve_global_address(uint64_t *global, const uint64_t addr) {
Vicent Martieca47832016-05-01 12:53:46 +020061 if (in_shared_object()) {
Vicent Marti040df7d2016-05-04 16:59:57 +020062 return (pid_ &&
63 !bcc_resolve_global_addr(*pid_, bin_path_.c_str(), addr, global));
Vicent Martieca47832016-05-01 12:53:46 +020064 }
65
66 *global = addr;
67 return true;
68}
69
Vicent Marti10436452016-05-04 16:58:51 +020070bool Probe::add_to_semaphore(int16_t val) {
Sasha Goldshtein9ca8ac22017-03-03 15:13:16 -050071 assert(pid_);
Vicent Marti10436452016-05-04 16:58:51 +020072
73 if (!attached_semaphore_) {
74 uint64_t addr;
75 if (!resolve_global_address(&addr, semaphore_))
76 return false;
77 attached_semaphore_ = addr;
Vicent Marti92598412016-04-28 19:42:55 +020078 }
79
Vicent Marti10436452016-05-04 16:58:51 +020080 off_t address = static_cast<off_t>(attached_semaphore_.value());
Vicent Marti92598412016-04-28 19:42:55 +020081
Vicent Marti10436452016-05-04 16:58:51 +020082 std::string procmem = tfm::format("/proc/%d/mem", pid_.value());
Vicent Marti92598412016-04-28 19:42:55 +020083 int memfd = ::open(procmem.c_str(), O_RDWR);
84 if (memfd < 0)
85 return false;
86
Vicent Marti10436452016-05-04 16:58:51 +020087 int16_t original;
Vicent Marti92598412016-04-28 19:42:55 +020088
Vicent Marti10436452016-05-04 16:58:51 +020089 if (::lseek(memfd, address, SEEK_SET) < 0 ||
Vicent Marti92598412016-04-28 19:42:55 +020090 ::read(memfd, &original, 2) != 2) {
91 ::close(memfd);
92 return false;
93 }
94
95 original = original + val;
96
Vicent Marti10436452016-05-04 16:58:51 +020097 if (::lseek(memfd, address, SEEK_SET) < 0 ||
Vicent Marti92598412016-04-28 19:42:55 +020098 ::write(memfd, &original, 2) != 2) {
99 ::close(memfd);
100 return false;
101 }
102
103 ::close(memfd);
104 return true;
105}
106
Vicent Marti10436452016-05-04 16:58:51 +0200107bool Probe::enable(const std::string &fn_name) {
108 if (attached_to_)
Vicent Marti92598412016-04-28 19:42:55 +0200109 return false;
110
Vicent Marti10436452016-05-04 16:58:51 +0200111 if (need_enable()) {
112 if (!pid_)
113 return false;
114
115 if (!add_to_semaphore(+1))
116 return false;
117 }
118
119 attached_to_ = fn_name;
Vicent Marti92598412016-04-28 19:42:55 +0200120 return true;
121}
122
Vicent Marti10436452016-05-04 16:58:51 +0200123bool Probe::disable() {
124 if (!attached_to_)
Vicent Marti92598412016-04-28 19:42:55 +0200125 return false;
126
Vicent Marti10436452016-05-04 16:58:51 +0200127 attached_to_ = nullopt;
Vicent Marti92598412016-04-28 19:42:55 +0200128
Vicent Marti10436452016-05-04 16:58:51 +0200129 if (need_enable()) {
130 assert(pid_);
131 return add_to_semaphore(-1);
132 }
133 return true;
Vicent Marti92598412016-04-28 19:42:55 +0200134}
135
Vicent Martieca47832016-05-01 12:53:46 +0200136std::string Probe::largest_arg_type(size_t arg_n) {
137 Argument *largest = nullptr;
138 for (Location &location : locations_) {
139 Argument *candidate = &location.arguments_[arg_n];
140 if (!largest ||
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200141 std::abs(candidate->arg_size()) > std::abs(largest->arg_size()))
Vicent Martieca47832016-05-01 12:53:46 +0200142 largest = candidate;
143 }
144
145 assert(largest);
146 return largest->ctype();
147}
148
Vicent Marti10436452016-05-04 16:58:51 +0200149bool Probe::usdt_getarg(std::ostream &stream) {
Vicent Martieca47832016-05-01 12:53:46 +0200150 const size_t arg_count = locations_[0].arguments_.size();
151
Vicent Marti10436452016-05-04 16:58:51 +0200152 if (!attached_to_)
153 return false;
154
Vicent Martieca47832016-05-01 12:53:46 +0200155 if (arg_count == 0)
156 return true;
157
158 for (size_t arg_n = 0; arg_n < arg_count; ++arg_n) {
159 std::string ctype = largest_arg_type(arg_n);
Yonghong Songe09564d2017-06-05 17:55:24 -0700160 std::string cptr = tfm::format("*((%s *)dest)", ctype);
Vicent Marti4ea4af42016-05-04 13:01:55 +0200161
Vicent Martieca47832016-05-01 12:53:46 +0200162 tfm::format(stream,
Sasha Goldshtein2070a2a2017-05-03 07:07:23 -0400163 "static __always_inline int _bpf_readarg_%s_%d("
Vicent Marti040df7d2016-05-04 16:59:57 +0200164 "struct pt_regs *ctx, void *dest, size_t len) {\n"
165 " if (len != sizeof(%s)) return -1;\n",
166 attached_to_.value(), arg_n + 1, ctype);
Vicent Martieca47832016-05-01 12:53:46 +0200167
168 if (locations_.size() == 1) {
169 Location &location = locations_.front();
170 stream << " ";
Vicent Marti040df7d2016-05-04 16:59:57 +0200171 if (!location.arguments_[arg_n].assign_to_local(stream, cptr, bin_path_,
172 pid_))
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200173 return false;
Vicent Marti4ea4af42016-05-04 13:01:55 +0200174 stream << "\n return 0;\n}\n";
Vicent Martieca47832016-05-01 12:53:46 +0200175 } else {
176 stream << " switch(ctx->ip) {\n";
177 for (Location &location : locations_) {
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200178 uint64_t global_address;
Vicent Martieca47832016-05-01 12:53:46 +0200179
Vicent Marti10436452016-05-04 16:58:51 +0200180 if (!resolve_global_address(&global_address, location.address_))
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200181 return false;
Vicent Martieca47832016-05-01 12:53:46 +0200182
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200183 tfm::format(stream, " case 0x%xULL: ", global_address);
Vicent Marti040df7d2016-05-04 16:59:57 +0200184 if (!location.arguments_[arg_n].assign_to_local(stream, cptr, bin_path_,
185 pid_))
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200186 return false;
Vicent Martieca47832016-05-01 12:53:46 +0200187
Vicent Marti4ea4af42016-05-04 13:01:55 +0200188 stream << " return 0;\n";
Vicent Martieca47832016-05-01 12:53:46 +0200189 }
190 stream << " }\n";
Vicent Marti4ea4af42016-05-04 13:01:55 +0200191 stream << " return -1;\n}\n";
Vicent Martieca47832016-05-01 12:53:46 +0200192 }
Vicent Martieca47832016-05-01 12:53:46 +0200193 }
194 return true;
195}
196
Vicent Marti0865f942016-04-27 16:57:58 +0200197void Probe::add_location(uint64_t addr, const char *fmt) {
198 locations_.emplace_back(addr, fmt);
199}
200
Teng Qin488c1192017-09-13 10:47:59 -0700201void Probe::finalize_locations() {
202 std::sort(locations_.begin(), locations_.end(),
203 [](const Location &a, const Location &b) {
204 return a.address_ < b.address_;
205 });
206 auto last = std::unique(locations_.begin(), locations_.end(),
207 [](const Location &a, const Location &b) {
208 return a.address_ == b.address_;
209 });
210 locations_.erase(last, locations_.end());
211}
212
Vicent Marti0865f942016-04-27 16:57:58 +0200213void Context::_each_probe(const char *binpath, const struct bcc_elf_usdt *probe,
214 void *p) {
215 Context *ctx = static_cast<Context *>(p);
216 ctx->add_probe(binpath, probe);
217}
218
Teng Qin3bfc8772017-05-04 12:09:19 -0700219int Context::_each_module(const char *modpath, uint64_t, uint64_t, bool, void *p) {
Sasha Goldshtein69948a62017-03-03 08:00:55 -0500220 Context *ctx = static_cast<Context *>(p);
221 // Modules may be reported multiple times if they contain more than one
222 // executable region. We are going to parse the ELF on disk anyway, so we
223 // don't need these duplicates.
224 if (ctx->modules_.insert(modpath).second /*inserted new?*/) {
Vicent Marti96c1b8e2017-06-27 19:06:46 +0200225 ProcMountNSGuard g(ctx->mount_ns_instance_.get());
Sasha Goldshtein69948a62017-03-03 08:00:55 -0500226 bcc_elf_foreach_usdt(modpath, _each_probe, p);
227 }
Vicent Marti92598412016-04-28 19:42:55 +0200228 return 0;
229}
230
Vicent Marti0865f942016-04-27 16:57:58 +0200231void Context::add_probe(const char *binpath, const struct bcc_elf_usdt *probe) {
Vicent Marti10436452016-05-04 16:58:51 +0200232 for (auto &p : probes_) {
Vicent Marti0865f942016-04-27 16:57:58 +0200233 if (p->provider_ == probe->provider && p->name_ == probe->name) {
Vicent Marti10436452016-05-04 16:58:51 +0200234 p->add_location(probe->pc, probe->arg_fmt);
235 return;
Vicent Marti0865f942016-04-27 16:57:58 +0200236 }
237 }
238
Vicent Marti040df7d2016-05-04 16:59:57 +0200239 probes_.emplace_back(
Vicent Marti96c1b8e2017-06-27 19:06:46 +0200240 new Probe(binpath, probe->provider, probe->name, probe->semaphore, pid_,
241 mount_ns_instance_.get()));
Vicent Marti10436452016-05-04 16:58:51 +0200242 probes_.back()->add_location(probe->pc, probe->arg_fmt);
Vicent Marti0865f942016-04-27 16:57:58 +0200243}
244
Vicent Marti92598412016-04-28 19:42:55 +0200245std::string Context::resolve_bin_path(const std::string &bin_path) {
246 std::string result;
247
248 if (char *which = bcc_procutils_which(bin_path.c_str())) {
249 result = which;
250 ::free(which);
Paul Chaignon81654bf2017-01-15 10:11:42 +0100251 } else if (char *which_so = bcc_procutils_which_so(bin_path.c_str(), 0)) {
Vicent Marti92598412016-04-28 19:42:55 +0200252 result = which_so;
Paul Chaignon81654bf2017-01-15 10:11:42 +0100253 ::free(which_so);
Vicent Marti92598412016-04-28 19:42:55 +0200254 }
255
256 return result;
Vicent Marti0865f942016-04-27 16:57:58 +0200257}
258
Vicent Marti11606082016-05-06 10:51:54 +0200259Probe *Context::get(const std::string &probe_name) {
Vicent Marti10436452016-05-04 16:58:51 +0200260 for (auto &p : probes_) {
Vicent Marti92598412016-04-28 19:42:55 +0200261 if (p->name_ == probe_name)
Vicent Marti11606082016-05-06 10:51:54 +0200262 return p.get();
Vicent Marti92598412016-04-28 19:42:55 +0200263 }
264 return nullptr;
265}
Vicent Marti0865f942016-04-27 16:57:58 +0200266
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200267bool Context::enable_probe(const std::string &probe_name,
268 const std::string &fn_name) {
Vicent Marti10436452016-05-04 16:58:51 +0200269 if (pid_stat_ && pid_stat_->is_stale())
Vicent Martieca47832016-05-01 12:53:46 +0200270 return false;
271
Vicent Marti10436452016-05-04 16:58:51 +0200272 auto p = get(probe_name);
273 return p && p->enable(fn_name);
Vicent Martieca47832016-05-01 12:53:46 +0200274}
275
Sasha Goldshtein69e361a2016-09-27 19:40:00 +0300276void Context::each(each_cb callback) {
277 for (const auto &probe : probes_) {
278 struct bcc_usdt info = {0};
279 info.provider = probe->provider().c_str();
280 info.bin_path = probe->bin_path().c_str();
281 info.name = probe->name().c_str();
282 info.semaphore = probe->semaphore();
283 info.num_locations = probe->num_locations();
284 info.num_arguments = probe->num_arguments();
285 callback(&info);
286 }
287}
288
Vicent Martieca47832016-05-01 12:53:46 +0200289void Context::each_uprobe(each_uprobe_cb callback) {
Vicent Marti10436452016-05-04 16:58:51 +0200290 for (auto &p : probes_) {
291 if (!p->enabled())
292 continue;
293
Sasha Goldshtein6e91a742016-10-06 18:18:18 +0300294 for (Location &loc : p->locations_) {
Vicent Marti10436452016-05-04 16:58:51 +0200295 callback(p->bin_path_.c_str(), p->attached_to_->c_str(), loc.address_,
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200296 pid_.value_or(-1));
Vicent Martieca47832016-05-01 12:53:46 +0200297 }
298 }
299}
300
Teng Qin137ee812017-08-25 16:29:16 -0700301Context::Context(const std::string &bin_path)
302 : mount_ns_instance_(new ProcMountNS(-1)), loaded_(false) {
Vicent Marti92598412016-04-28 19:42:55 +0200303 std::string full_path = resolve_bin_path(bin_path);
304 if (!full_path.empty()) {
Yonghong Song0ba15072017-07-21 22:13:20 -0700305 if (bcc_elf_foreach_usdt(full_path.c_str(), _each_probe, this) == 0) {
306 cmd_bin_path_ = full_path;
Vicent Marti92598412016-04-28 19:42:55 +0200307 loaded_ = true;
Yonghong Song0ba15072017-07-21 22:13:20 -0700308 }
Vicent Marti92598412016-04-28 19:42:55 +0200309 }
Teng Qin488c1192017-09-13 10:47:59 -0700310 for (const auto &probe : probes_)
311 probe->finalize_locations();
Vicent Marti92598412016-04-28 19:42:55 +0200312}
313
Vicent Marti96c1b8e2017-06-27 19:06:46 +0200314Context::Context(int pid) : pid_(pid), pid_stat_(pid),
315 mount_ns_instance_(new ProcMountNS(pid)), loaded_(false) {
Yonghong Song0ba15072017-07-21 22:13:20 -0700316 if (bcc_procutils_each_module(pid, _each_module, this) == 0) {
317 // get exe command from /proc/<pid>/exe
318 // assume the maximum path length 4096, which should be
319 // sufficiently large to cover all use cases
320 char source[64];
321 char cmd_buf[4096];
322 snprintf(source, sizeof(source), "/proc/%d/exe", pid);
323 ssize_t cmd_len = readlink(source, cmd_buf, sizeof(cmd_buf) - 1);
324 if (cmd_len == -1)
325 return;
326 cmd_buf[cmd_len] = '\0';
327 cmd_bin_path_.assign(cmd_buf, cmd_len + 1);
328
Vicent Marti92598412016-04-28 19:42:55 +0200329 loaded_ = true;
Yonghong Song0ba15072017-07-21 22:13:20 -0700330 }
Teng Qin488c1192017-09-13 10:47:59 -0700331 for (const auto &probe : probes_)
332 probe->finalize_locations();
Vicent Marti92598412016-04-28 19:42:55 +0200333}
Vicent Martieca47832016-05-01 12:53:46 +0200334
335Context::~Context() {
Vicent Marti10436452016-05-04 16:58:51 +0200336 if (pid_stat_ && !pid_stat_->is_stale()) {
Vicent Marti040df7d2016-05-04 16:59:57 +0200337 for (auto &p : probes_) p->disable();
Vicent Martieca47832016-05-01 12:53:46 +0200338 }
339}
Vicent Martieca47832016-05-01 12:53:46 +0200340}
341
342extern "C" {
Vicent Martieca47832016-05-01 12:53:46 +0200343
344void *bcc_usdt_new_frompid(int pid) {
345 USDT::Context *ctx = new USDT::Context(pid);
346 if (!ctx->loaded()) {
347 delete ctx;
348 return nullptr;
349 }
350 return static_cast<void *>(ctx);
351}
352
353void *bcc_usdt_new_frompath(const char *path) {
354 USDT::Context *ctx = new USDT::Context(path);
355 if (!ctx->loaded()) {
356 delete ctx;
357 return nullptr;
358 }
359 return static_cast<void *>(ctx);
360}
361
362void bcc_usdt_close(void *usdt) {
363 USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
364 delete ctx;
365}
366
Vicent Marti1a2ddac2016-05-01 13:41:33 +0200367int bcc_usdt_enable_probe(void *usdt, const char *probe_name,
368 const char *fn_name) {
Vicent Martieca47832016-05-01 12:53:46 +0200369 USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
370 return ctx->enable_probe(probe_name, fn_name) ? 0 : -1;
371}
372
Yonghong Song0ba15072017-07-21 22:13:20 -0700373const char *bcc_usdt_genargs(void **usdt_array, int len) {
Brendan Gregg4f88a942016-07-22 17:11:51 -0700374 static std::string storage_;
Vicent Martieca47832016-05-01 12:53:46 +0200375 std::ostringstream stream;
Yonghong Song0ba15072017-07-21 22:13:20 -0700376
Brenden Blanco4cb1edb2017-08-16 11:26:14 -0700377 if (!len)
378 return "";
379
Yonghong Song0ba15072017-07-21 22:13:20 -0700380 stream << USDT::USDT_PROGRAM_HEADER;
381 // Generate genargs codes for an array of USDT Contexts.
382 //
383 // Each mnt_point + cmd_bin_path + probe_provider + probe_name
384 // uniquely identifies a probe.
385 std::unordered_set<std::string> generated_probes;
386 for (int i = 0; i < len; i++) {
387 USDT::Context *ctx = static_cast<USDT::Context *>(usdt_array[i]);
388
389 for (size_t j = 0; j < ctx->num_probes(); j++) {
390 USDT::Probe *p = ctx->get(j);
391 if (p->enabled()) {
392 std::string key = std::to_string(ctx->inode()) + "*"
393 + ctx->cmd_bin_path() + "*" + p->provider() + "*" + p->name();
394 if (generated_probes.find(key) != generated_probes.end())
395 continue;
396 if (!p->usdt_getarg(stream))
397 return nullptr;
398 generated_probes.insert(key);
399 }
400 }
401 }
Brendan Gregg4f88a942016-07-22 17:11:51 -0700402
403 storage_ = stream.str();
404 return storage_.c_str();
Vicent Martieca47832016-05-01 12:53:46 +0200405}
406
Teng Qin0615bff2016-09-28 08:19:40 -0700407const char *bcc_usdt_get_probe_argctype(
408 void *ctx, const char* probe_name, const int arg_index
409) {
410 USDT::Probe *p = static_cast<USDT::Context *>(ctx)->get(probe_name);
411 std::string res = p ? p->get_arg_ctype(arg_index) : "";
412 return res.c_str();
413}
414
Sasha Goldshtein69e361a2016-09-27 19:40:00 +0300415void bcc_usdt_foreach(void *usdt, bcc_usdt_cb callback) {
416 USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
417 ctx->each(callback);
418}
419
Sasha Goldshtein6e91a742016-10-06 18:18:18 +0300420int bcc_usdt_get_location(void *usdt, const char *probe_name,
421 int index, struct bcc_usdt_location *location) {
Sasha Goldshtein8698bdb2017-02-19 20:29:45 +0000422 USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
423 USDT::Probe *probe = ctx->get(probe_name);
424 if (!probe)
425 return -1;
426 if (index < 0 || (size_t)index >= probe->num_locations())
427 return -1;
428 location->address = probe->address(index);
429 return 0;
Sasha Goldshtein6e91a742016-10-06 18:18:18 +0300430}
431
432int bcc_usdt_get_argument(void *usdt, const char *probe_name,
433 int location_index, int argument_index,
434 struct bcc_usdt_argument *argument) {
Sasha Goldshtein8698bdb2017-02-19 20:29:45 +0000435 USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
436 USDT::Probe *probe = ctx->get(probe_name);
437 if (!probe)
438 return -1;
439 if (argument_index < 0 || (size_t)argument_index >= probe->num_arguments())
440 return -1;
441 if (location_index < 0 || (size_t)location_index >= probe->num_locations())
442 return -1;
443 auto const &location = probe->location(location_index);
444 auto const &arg = location.arguments_[argument_index];
445 argument->size = arg.arg_size();
446 argument->valid = BCC_USDT_ARGUMENT_NONE;
447 if (arg.constant()) {
448 argument->valid |= BCC_USDT_ARGUMENT_CONSTANT;
449 argument->constant = *(arg.constant());
450 }
451 if (arg.deref_offset()) {
452 argument->valid |= BCC_USDT_ARGUMENT_DEREF_OFFSET;
453 argument->deref_offset = *(arg.deref_offset());
454 }
455 if (arg.deref_ident()) {
456 argument->valid |= BCC_USDT_ARGUMENT_DEREF_IDENT;
457 argument->deref_ident = arg.deref_ident()->c_str();
458 }
459 if (arg.base_register_name()) {
460 argument->valid |= BCC_USDT_ARGUMENT_BASE_REGISTER_NAME;
461 argument->base_register_name = arg.base_register_name()->c_str();
462 }
463 if (arg.index_register_name()) {
464 argument->valid |= BCC_USDT_ARGUMENT_INDEX_REGISTER_NAME;
465 argument->index_register_name = arg.index_register_name()->c_str();
466 }
467 if (arg.scale()) {
468 argument->valid |= BCC_USDT_ARGUMENT_SCALE;
469 argument->scale = *(arg.scale());
470 }
471 return 0;
Sasha Goldshtein6e91a742016-10-06 18:18:18 +0300472}
473
Vicent Martieca47832016-05-01 12:53:46 +0200474void bcc_usdt_foreach_uprobe(void *usdt, bcc_usdt_uprobe_cb callback) {
475 USDT::Context *ctx = static_cast<USDT::Context *>(usdt);
476 ctx->each_uprobe(callback);
477}
Vicent Marti0865f942016-04-27 16:57:58 +0200478}