Start registers and starts an event tracing session. The session remains active until the session is stopped, the machine is restarted, or an error occurs that would interrupt the session.
()
| 255 | // the machine is restarted, or an error occurs that would |
| 256 | // interrupt the session. |
| 257 | func (t *Trace) Start() error { |
| 258 | if len(t.Name) > maxLoggerNameSize { |
| 259 | return fmt.Errorf("trace name [%s] is too long", t.Name) |
| 260 | } |
| 261 | |
| 262 | if !t.IsGUIDEmpty() && t.HasProviders() { |
| 263 | return fmt.Errorf("%s trace has the root GUID set but providers are not empty", t.Name) |
| 264 | } |
| 265 | |
| 266 | cfg := t.config.EventSource |
| 267 | props := initEventTraceProps(cfg) |
| 268 | flags := t.enableFlagsDynamically(cfg) |
| 269 | |
| 270 | if t.IsKernelTrace() { |
| 271 | props.EnableFlags = flags |
| 272 | props.Wnode.GUID = t.GUID |
| 273 | log.Debugf("starting kernel trace with %q event flags", props.EnableFlags) |
| 274 | } |
| 275 | |
| 276 | log.Debugf("starting trace [%s]", t.Name) |
| 277 | |
| 278 | var err error |
| 279 | t.startHandle, err = etw.StartTrace( |
| 280 | t.Name, |
| 281 | props, |
| 282 | ) |
| 283 | if err != nil { |
| 284 | return err |
| 285 | } |
| 286 | if !t.startHandle.IsValid() { |
| 287 | return errs.ErrInvalidTrace |
| 288 | } |
| 289 | |
| 290 | if t.IsKernelTrace() { |
| 291 | handle := t.startHandle |
| 292 | // poorly documented ETW feature that allows for enabling an extended set of |
| 293 | // kernel event tracing flags. According to the MSDN documentation, aside from |
| 294 | // invoking `EventTraceProperties` function to enable object manager tracking |
| 295 | // the `EventTraceProperties` structure's `EnableFlags` member needs to be set |
| 296 | // to PERF_OB_HANDLE (0x80000040). This actually results in an erroneous trace start. |
| 297 | // The documentation neither specifies how the function should be called, group mask |
| 298 | // array with its 4th element set to 0x80000040. |
| 299 | sysTraceFlags := make([]etw.EventTraceFlags, 8) |
| 300 | // when we call `TraceSetInformation` with event empty group mask reserved for the |
| 301 | // flags that are bitvectored into `EventTraceProperties` structure's `EnableFlags` field, |
| 302 | // it will trigger the arrival of rundown events including open file objects and |
| 303 | // registry keys that are very valuable for us to construct the initial snapshot of |
| 304 | // these system resources and let us build the state machine |
| 305 | if err := etw.SetTraceSystemFlags(handle, sysTraceFlags); err != nil { |
| 306 | log.Warnf("unable to set empty system flags: %v", err) |
| 307 | return nil |
| 308 | } |
| 309 | |
| 310 | sysTraceFlags[0] = flags |
| 311 | |
| 312 | // enable object manager tracking |
| 313 | if cfg.EnableHandleEvents { |
| 314 | sysTraceFlags[4] = etw.Handle |