3 import { basename } from "fs";
4 let udebug = require("udebug");
5 let uloop = require("uloop");
6 let libubus = require("ubus");
8 let ubus = libubus.connect();
14 const usage_message = `
15 Usage: ${basename(sourcepath())} [<options>] <command> [<args>]
18 -f Ignore errors on opening rings
19 -d <duration>: Only fetch data up to <duration> seconds old
20 -o <file>|- Set output file for snapshot/stream (or '-' for stdout)
21 -i <process>[:<name>] Select debug buffer for snapshot/stream
22 -s <path> Use udebug socket <path>
23 -q Suppress warnings/error messages
26 list: List available debug buffers
27 snapshot: Create a pcapng snapshot of debug buffers
28 set_flag [<name>=0|1 ...] Set ring buffer flags
29 get_flags Get ring buffer flags
45 while (substr(ARGV[0], 0, 1) == "-") {
46 let opt = substr(shift(ARGV), 1);
49 opts.duration = 1.0 * shift(ARGV);
52 opts.socket = shift(ARGV);
55 push(opts.select, shift(ARGV));
58 opts.output_file = shift(ARGV);
77 function ring_selected(ring) {
78 if (!length(opts.select))
81 for (let sel in opts.select) {
82 let match = split(sel, ":", 2);
83 if (wildcard(ring.proc_name, match[0]) &&
84 (!match[1] || wildcard(ring.ring_name, match[1])))
91 function poll_data() {
93 for (let ring_id in rings) {
94 let ring = rings[ring_id];
95 let s = ring[1].fetch();
103 function open_ring(ring, poll) {
104 let ring_name =` ${ring.proc_name}:${ring.ring_name}`;
105 let ref = udebug.get_ring(ring);
110 ref.set_fetch_duration(opts.duration);
112 ref.set_poll_cb(() => { poll_data() });
114 let ring_id = ring.id + "";
115 ring = [ ring_name, ref ];
116 rings[ring_id] = ring;
121 function open_output() {
122 if (!opts.output_file) {
123 _warn(`No output file\n`);
126 let out = opts.output_file;
130 pcap = udebug.pcap_file(out);
132 _warn(`Failed to open output\n`);
139 for (let proc in procs) {
140 print(`Process ${proc}:\n`);
141 for (let ring in procs[proc])
142 print(` - ${ring.ring_name}\n`);
145 snapshot: function() {
148 if (!length(selected)) {
149 _warn(`No available debug buffers\n`);
153 for (let ring in selected) {
154 if (!open_ring(ring)) {
155 _warn(`Failed to open ring ${ring_name}\n`);
166 set_flag: function() {
167 for (let ring in selected) {
168 if (!length(ring.flags))
171 let mask = 0, set = 0;
172 for (let flag in ring.flags) {
173 for (let change in ARGV) {
174 change = split(change, "=", 2);
175 let name = change[0];
176 let val = !!int(change[1]);
188 let r = open_ring(ring);
192 r[1].change_flags(mask, set);
195 get_flags: function() {
196 for (let ring in selected) {
197 if (!length(ring.flags))
200 let r = open_ring(ring);
205 let flags = r[1].get_flags();
206 for (let flag in ring.flags)
207 print(`\t${flag[0]}=${((flags & flag[1]) == flag[1]) ? 1 : 0 }\n`);
213 subscriber = ubus.subscriber((req) => {
216 let ring_id = ring.id + "";
217 if (type == "remove") {
218 ring = rings[ring_id];
223 delete rings[ring_id];
224 } else if (type == "add") {
225 open_ring(ring, true);
229 subscriber.subscribe("udebug");
230 for (let ring in selected) {
231 if (!open_ring(ring, true)) {
232 _warn(`Failed to open ring ${ring_name}\n`);
240 let done = () => { uloop.done(); };
241 signal('SIGINT', done);
242 signal('SIGTERM', done);
245 delete opts.duration;
250 let cmd = shift(ARGV);
254 let ring_list = ubus.call("udebug", "list");
255 if (!ring_list || !ring_list.results) {
256 warn("Failed to get ring buffer list from udebugd\n");
260 ring_list = ring_list.results;
261 for (let ring in ring_list) {
262 if (!ring_selected(ring))
265 let proc = procs[ring.proc_name];
268 procs[ring.proc_name] = proc;
271 push(selected, ring);
274 if (cmd != "list" && !udebug.init(opts.socket)) {
275 _warn(`Failed to connect to udebug socket\n`);