unwind-stack-user.dhover×718all
#!/usr/bin/env dub
/+ dub.sdl:
    name "cpu_pmu_unwind_stack_user"
    platforms "linux"
    libs "dw" "elf"
    dflags "-g"
    dflags "--frame-pointer=none" platform="ldc"
    targetPath "build"
+/
/**
 * DWARF-CFI stack unwinding from `PERF_SAMPLE_STACK_USER` + `PERF_SAMPLE_REGS_USER`
 * on a frame-pointer-less build — the "call-graph profiler" acquisition path.
 *
 * Frame-pointer omission (`--frame-pointer=none`; applied under LDC only —
 * DMD has no such switch, so a DMD build keeps frame pointers while the CFI
 * unwind path stays identical) makes the classic `%rbp`
 * chain-walk impossible, so a backtrace must come from DWARF Call Frame
 * Information. We arm `cycles` sampling that, on each overflow, additionally
 * copies the interrupted thread's **register file** (`REGS_USER`) and a slab of
 * its **user stack** (`STACK_USER`) into the ring buffer. Offline, we feed those
 * to elfutils `libdwfl`'s frame API — `dwfl_attach_state` with a
 * `Dwfl_Thread_Callbacks` whose `memory_read` serves bytes from the captured
 * stack slab and whose `set_initial_registers` seeds the captured registers,
 * then `dwfl_getthread_frames` drives the CFI unwinder frame by frame
 * (`dwfl_frame_pc`) — exactly the wiring `perf`'s `unwind-libdw.c` uses.
 *
 * The probe has two guaranteed stages: (1) it demonstrably *captures* the
 * registers + stack (printing the register ABI, key registers, and stack
 * `dyn_size`); (2) it attempts the full in-process CFI unwind and prints the
 * recovered backtrace. If the unwind cannot complete in-process it degrades to
 * stage 1 and notes that the unwind API path is grounded by source-reading —
 * either way it exits 0.
 *
 * Companion to docs/research/cpu-pmu/linux-perf-events.md
 *   § "Stack unwinding: `STACK_USER` + `REGS_USER` and DWARF CFI" and
 *   docs/research/cpu-pmu/elfutils.md § "DWARF-CFI stack unwinding".
 *
 * Run with: nix shell nixpkgs#elfutils nixpkgs#pkg-config -c dub run --single unwind-stack-user.d
 *
 * Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4, x86-64),
 * `/proc/sys/kernel/perf_event_paranoid` = -1, elfutils 0.195 (libdw/libdwfl),
 * LDC 1.41 druntime `core.sys.linux.perf_event`. Linked with the flake
 * stdenv dynamic linker (glibc 2.42) so elfutils 0.195 can resolve
 * `GLIBC_ABI_GNU2_TLS` — see nix/d-toolchain.nix. The perf→DWARF
 * register mapping below is x86-64-specific.
 *
 * Portability: any missing capability prints a `SKIP:` line and exits 0.
 */
module 
(module) cpu_pmu_unwind_stack_user

DWARF-CFI stack unwinding from PERF_SAMPLE_STACK_USER + PERF_SAMPLE_REGS_USER on a frame-pointer-less build — the "call-graph profiler" acquisition path.

Frame-pointer omission (--frame-pointer=none; applied under LDC only — DMD has no such switch, so a DMD build keeps frame pointers while the CFI unwind path stays identical) makes the classic %rbp chain-walk impossible, so a backtrace must come from DWARF Call Frame Information. We arm cycles sampling that, on each overflow, additionally copies the interrupted thread's register file (REGS_USER) and a slab of its user stack (STACK_USER) into the ring buffer. Offline, we feed those to elfutils libdwfl's frame API — dwfl_attach_state with a Dwfl_Thread_Callbacks whose memory_read serves bytes from the captured stack slab and whose set_initial_registers seeds the captured registers, then dwfl_getthread_frames drives the CFI unwinder frame by frame (dwfl_frame_pc) — exactly the wiring perf's unwind-libdw.c uses.

The probe has two guaranteed stages: (1) it demonstrably captures the registers + stack (printing the register ABI, key registers, and stack dyn_size); (2) it attempts the full in-process CFI unwind and prints the recovered backtrace. If the unwind cannot complete in-process it degrades to stage 1 and notes that the unwind API path is grounded by source-reading — either way it exits 0.

Companion to docs/research/cpu-pmu/linux-perf-events.md § "Stack unwinding: STACK_USER + REGS_USER and DWARF CFI" and docs/research/cpu-pmu/elfutils.md § "DWARF-CFI stack unwinding".

Run with: nix shell nixpkgs#elfutils nixpkgs#pkg-config -c dub run --single unwind-stack-user.d

Environment recorded: Linux 6.18.26, AMD Ryzen 9 7940HX (Zen 4, x86-64), /proc/sys/kernel/perf_event_paranoid = -1, elfutils 0.195 (libdw/libdwfl), LDC 1.41 druntime core.sys.linux.perf_event. Linked with the flake stdenv dynamic linker (glibc 2.42) so elfutils 0.195 can resolve GLIBC_ABI_GNU2_TLS — see nix/d-toolchain.nix. The perf→DWARF register mapping below is x86-64-specific.

Portability

any missing capability prints a SKIP: line and exits 0.

cpu_pmu_unwind_stack_user
;
version (
linux
linux
)
{ version (
X86_64
X86_64
) {}
else version = NotX86_64; } version (
linux
linux
)
version (
X86_64
X86_64
)
{ import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.linux
linux
.
(module) core.sys.linux.perf_event

D header file for perf_event_open system call.

Converted from linux userspace header, comments included.

@authorsMax Haughton
perf_event
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(module) core.sys.posix.unistd

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly@standardsThe Open Group Base Specifications Issue 8, IEEE Std 1003.1, 2024 Edition
unistd
:
(alias) cpu_pmu_unwind_stack_user.close = int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
,
(alias) cpu_pmu_unwind_stack_user.getpid = int core.sys.posix.unistd.getpid() nothrow @nogc @trusted
getpid
,
(alias) cpu_pmu_unwind_stack_user.sysconf = long core.sys.posix.unistd.sysconf(int) nothrow @nogc @trusted
sysconf
,
(alias enum value) cpu_pmu_unwind_stack_user._SC_PAGESIZE = core.sys.posix.unistd._SC_PAGESIZE = 30
_SC_PAGESIZE
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(package) core.sys.posix.sys
sys
.
(module) core.sys.posix.sys.ioctl

D header file for POSIX.

@copyrightCopyright Alex Rønne Petersen 2011 - 2012.@licenseBoost License 1.0.@authorsAlex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
ioctl
:
(alias) cpu_pmu_unwind_stack_user.ioctl = int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
;
import
(package) core
core
.
(package) core.sys
sys
.
(package) core.sys.posix
posix
.
(package) core.sys.posix.sys
sys
.
(module) core.sys.posix.sys.mman

D header file for POSIX.

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseBoost License 1.0.@authorsSean Kelly, Alex Rønne Petersen@standardsThe Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition
mman
: mmap,
(alias) cpu_pmu_unwind_stack_user.munmap = int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogc
munmap
,
(alias constant) cpu_pmu_unwind_stack_user.PROT_READ = int core.sys.posix.sys.mman.PROT_READ = 1
PROT_READ
,
(alias constant) cpu_pmu_unwind_stack_user.PROT_WRITE = int core.sys.posix.sys.mman.PROT_WRITE = 2
PROT_WRITE
,
(alias constant) cpu_pmu_unwind_stack_user.MAP_SHARED = int core.sys.posix.sys.mman.MAP_SHARED = 1
MAP_SHARED
,
(alias constant) cpu_pmu_unwind_stack_user.MAP_FAILED = void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LU
MAP_FAILED
;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.config

D compatible types that correspond to various basic types in associated C and C++ compilers.

Source

core/stdc/config.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
config
: c_ulong;
import
(package) core
core
.
(package) core.stdc
stdc
.
(module) core.stdc.string

D header file for C99.

pubs.opengroup.org/onlinepubs/009695399/basedefs/string.h.html, string.h

Source

core/stdc/string.d

@copyrightCopyright Sean Kelly 2005 - 2009.@licenseDistributed under the Boost Software License 1.0. (See accompanying file LICENSE)@authorsSean Kelly@standardsISO/IEC 9899:1999 (E)
string
:
(alias) cpu_pmu_unwind_stack_user.memcpy = void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
;
import
(package) core
core
.
(module) core.atomic

The atomic module provides basic support for lock-free concurrent programming.

Use the -preview=nosharedaccess compiler flag to detect unsafe individual read or write operations on shared data.

Source

core/atomic.d

Examples

int y = 2;
shared int x = y; // OK

//x++; // read modify write error
x.atomicOp!"+="(1); // OK
//y = x; // read error with preview flag
y = x.atomicLoad(); // OK
assert(y == 3);
//x = 5; // write error with preview flag
x.atomicStore(5); // OK
assert(x.atomicLoad() == 5);
@copyrightCopyright Sean Kelly 2005 - 2016.@licenseBoost License 1.0@authorsSean Kelly, Alex Rønne Petersen, Manu Evans
atomic
:
(alias template) cpu_pmu_unwind_stack_user.atomicLoad = core.atomic.atomicLoad(MemoryOrder ms = MemoryOrder.seq, T)(auto ref return scope const T val) if (!is(T == shared(U), U) && !is(T == shared(inout(U)), U) && !is(T == shared(const(U)), U))

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
,
(alias template) cpu_pmu_unwind_stack_user.atomicStore = core.atomic.atomicStore(MemoryOrder ms = MemoryOrder.seq, T, V)(ref T val, V newval) if (!is(T == shared) && !is(V == shared))

Writes 'newval' into 'val'. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.rel, and MemoryOrder.seq.

@paramval The target variable.@paramnewval The value to store.
atomicStore
,
(enum) core.atomic.MemoryOrder

Specifies the memory ordering semantics of an atomic operation.

@see
MemoryOrder
;
import
(package) core
core
.
(module) core.time

Module containing core time functionality, such as Duration (which represents a duration of time) or MonoTime (which represents a timestamp of the system's monotonic clock).

Various functions take a string (or strings) to represent a unit of time (e.g. convert!("days", "hours")(numDays)). The valid strings to use with such functions are "years", "months", "weeks", "days", "hours", "minutes", "seconds", "msecs" (milliseconds), "usecs" (microseconds), "hnsecs" (hecto-nanoseconds - i.e. 100 ns) or some subset thereof. There are a few functions that also allow "nsecs", but very little actually has precision greater than hnsecs.

Symbol Description
Types
Duration Represents a duration of time of weeks or less (kept internally as hnsecs). (e.g. 22 days or 700 seconds).
TickDuration DEPRECATED Represents a duration of time in system clock ticks, using the highest precision that the system provides.
MonoTime Represents a monotonic timestamp in system clock ticks, using the highest precision that the system provides.
Functions
convert Generic way of converting between two time units.
dur Allows constructing a Duration from the given time units with the given length.
weeks days hours

minutes seconds msecs

usecs hnsecs nsecs | Convenience aliases for dur. | | abs | Returns the absolute value of a duration. |

From Duration
From TickDuration
From units
To Duration
tickDuration.to, std,conv!Duration()
dur!"msecs"(5) or 5.msecs()

| To TickDuration | duration.to, std,conv!TickDuration() |

  • | TickDuration.from!"msecs"(msecs) |

| To units | duration.total!"days" | tickDuration.msecs | convert!("days", "msecs")(msecs) |

Source

core/time.d

@copyrightCopyright 2010 - 2012@licenseBoost License 1.0.@authorsJonathan M Davis and Kato Shoichi
time
:
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
, msecs;
import
(package) std
std
.
(module) std.stdio
Category Symbols
File handles _popen File isFileHandle openNetwork stderr stdin stdout
Reading chunks lines readf readfln readln
Writing toFile write writef writefln writeln
Misc KeepTerminator LockType StdioException

Standard I/O functions that extend core.stdc.stdio. core.stdc.stdio is publically imported when importing std.stdio.

There are three layers of I/O:

  1. The lowest layer is the operating system layer. The two main schemes are Windows and Posix.

  2. C's stdio.h which unifies the two operating system schemes.

  3. std.stdio, this module, unifies the various stdio.h implementations into a high level package for D programs.

Source

std/stdio.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Alex Rønne Petersen
stdio
:
(alias template) cpu_pmu_unwind_stack_user.writefln = std.stdio.writefln(alias fmt, A...)(A args) if (isSomeString!(typeof(fmt)))

Equivalent to writef(fmt, args, '\n').

writefln
,
(alias template) cpu_pmu_unwind_stack_user.writeln = std.stdio.writeln(T...)(T args)

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
;
import
(package) std
std
.
(module) std.string

String handling functions.

Category Functions
Searching
column
indexOf
indexOfAny
indexOfNeither
lastIndexOf
lastIndexOfAny
lastIndexOfNeither
Comparison
isNumeric
Mutation
capitalize
Pruning and Filling
center
chomp
chompPrefix
chop
detabber
detab
entab
entabber
leftJustify
outdent
rightJustify
strip
stripLeft
stripRight
wrap
Substitution
abbrev
soundex
soundexer
succ
tr
translate
Miscellaneous
assumeUTF
fromStringz
lineSplitter
representation
splitLines
toStringz
Objects of types string, wstring, and dstring are value types
and cannot be mutated element-by-element. For using mutation during building
strings, use char[], wchar[], or dchar[]. The xxxstring
types are preferable because they don't exhibit undesired aliasing, thus
making code more robust.

The following functions are publicly imported:

Module Functions
Publicly imported functions
std.algorithm
cmp, std,algorithm,comparison
count, std,algorithm,searching
endsWith, std,algorithm,searching
startsWith, std,algorithm,searching
std.array
join, std,array
replace, std,array
replaceInPlace, std,array
split, std,array
empty, std,array
std.format
format, std,format
sformat, std,format
std.uni
icmp, std,uni
toLower, std,uni
toLowerInPlace, std,uni
toUpper, std,uni
toUpperInPlace, std,uni
There is a rich set of functions for string handling defined in other modules.
Functions related to Unicode and ASCII are found in std.uni
and std.ascii, respectively. Other functions that have a
wider generality than just strings can be found in std.algorithm
and std.range.

Source

std/string.d

@seestd.algorithm and std.range for generic range algorithms , std.ascii for functions that work with ASCII strings , std.uni for functions that work with unicode strings@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Jonathan M Davis, and David L. 'SpottedTiger' Davis
string
:
(alias template) cpu_pmu_unwind_stack_user.fromStringz = std.string.fromStringz(Char)(return scope inout(Char)* cString) if (isSomeChar!Char)
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
;
// ---- elfutils libdwfl: extern(C) prototypes ------------------------ alias
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
= ulong;
alias
(alias) cpu_pmu_unwind_stack_user.Dwarf_Word = ulong
Dwarf_Word
= ulong;
alias
(alias) cpu_pmu_unwind_stack_user.GElf_Addr = ulong
GElf_Addr
= ulong;
alias
(alias) cpu_pmu_unwind_stack_user.GElf_Off = ulong
GElf_Off
= ulong;
alias
(alias) cpu_pmu_unwind_stack_user.GElf_Word = uint
GElf_Word
= uint;
struct
(struct) cpu_pmu_unwind_stack_user.GElf_Sym
GElf_Sym
{ uint
(field) uint cpu_pmu_unwind_stack_user.GElf_Sym.st_name
st_name
;
ubyte
(field) ubyte cpu_pmu_unwind_stack_user.GElf_Sym.st_info
st_info
;
ubyte
(field) ubyte cpu_pmu_unwind_stack_user.GElf_Sym.st_other
st_other
;
ushort
(field) ushort cpu_pmu_unwind_stack_user.GElf_Sym.st_shndx
st_shndx
;
ulong
(field) ulong cpu_pmu_unwind_stack_user.GElf_Sym.st_value
st_value
;
ulong
(field) ulong cpu_pmu_unwind_stack_user.GElf_Sym.st_size
st_size
;
} struct
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
;
struct
(struct) cpu_pmu_unwind_stack_user.Dwfl_Module
Dwfl_Module
;
struct
(struct) cpu_pmu_unwind_stack_user.Dwfl_Frame
Dwfl_Frame
;
struct
(struct) cpu_pmu_unwind_stack_user.Dwfl_Thread
Dwfl_Thread
;
struct
(struct) cpu_pmu_unwind_stack_user.Elf
Elf
;
/// `Dwfl_Callbacks` (find_elf, find_debuginfo, section_address, debuginfo_path). struct
(struct) cpu_pmu_unwind_stack_user.DwflCallbacks

Dwfl_Callbacks (find_elf, find_debuginfo, section_address, debuginfo_path).

DwflCallbacks
{ void*
(field) void* cpu_pmu_unwind_stack_user.DwflCallbacks.find_elf
find_elf
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflCallbacks.find_debuginfo
find_debuginfo
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflCallbacks.section_address
section_address
;
char**
(field) char** cpu_pmu_unwind_stack_user.DwflCallbacks.debuginfo_path
debuginfo_path
;
} /// `Dwfl_Thread_Callbacks` (elfutils@6f8f78c libdwfl/libdwfl.h:661): field /// order next_thread, get_thread, memory_read, set_initial_registers, /// detach, thread_detach. struct
(struct) cpu_pmu_unwind_stack_user.DwflThreadCallbacks

Dwfl_Thread_Callbacks (elfutils@6f8f78c libdwfl/libdwfl.h:661): field order next_thread, get_thread, memory_read, set_initial_registers, detach, thread_detach.

DwflThreadCallbacks
{ void*
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.next_thread
next_thread
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.get_thread
get_thread
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.memory_read
memory_read
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.set_initial_registers
set_initial_registers
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.detach
detach
;
void*
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.thread_detach
thread_detach
;
} extern (C) @nogc nothrow {
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*
cpu_pmu_unwind_stack_user.Dwfl* cpu_pmu_unwind_stack_user.dwfl_begin(const(cpu_pmu_unwind_stack_user.DwflCallbacks)*) nothrow @nogc
dwfl_begin
(const(
(struct) cpu_pmu_unwind_stack_user.DwflCallbacks

Dwfl_Callbacks (find_elf, find_debuginfo, section_address, debuginfo_path).

DwflCallbacks
)*);
void
void cpu_pmu_unwind_stack_user.dwfl_end(cpu_pmu_unwind_stack_user.Dwfl*) nothrow @nogc
dwfl_end
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*);
int
int cpu_pmu_unwind_stack_user.dwfl_linux_proc_report(cpu_pmu_unwind_stack_user.Dwfl*, int pid) nothrow @nogc
dwfl_linux_proc_report
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*, int
(parameter) int pid
pid
);
int
int cpu_pmu_unwind_stack_user.dwfl_report_end(cpu_pmu_unwind_stack_user.Dwfl*, void* removed, void* arg) nothrow @nogc
dwfl_report_end
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*, void*
(parameter) void* removed
removed
, void*
(parameter) void* arg
arg
);
(struct) cpu_pmu_unwind_stack_user.Dwfl_Module
Dwfl_Module
*
cpu_pmu_unwind_stack_user.Dwfl_Module* cpu_pmu_unwind_stack_user.dwfl_addrmodule(cpu_pmu_unwind_stack_user.Dwfl*, ulong) nothrow @nogc
dwfl_addrmodule
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*,
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
);
const(char)*
const(char)* cpu_pmu_unwind_stack_user.dwfl_module_addrinfo(cpu_pmu_unwind_stack_user.Dwfl_Module*, ulong, ulong*, cpu_pmu_unwind_stack_user.GElf_Sym*, uint*, cpu_pmu_unwind_stack_user.Elf**, ulong*) nothrow @nogc
dwfl_module_addrinfo
(
(struct) cpu_pmu_unwind_stack_user.Dwfl_Module
Dwfl_Module
*,
(alias) cpu_pmu_unwind_stack_user.GElf_Addr = ulong
GElf_Addr
,
(alias) cpu_pmu_unwind_stack_user.GElf_Off = ulong
GElf_Off
*,
(struct) cpu_pmu_unwind_stack_user.GElf_Sym
GElf_Sym
*,
(alias) cpu_pmu_unwind_stack_user.GElf_Word = uint
GElf_Word
*,
(struct) cpu_pmu_unwind_stack_user.Elf
Elf
**,
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
*);
bool
bool cpu_pmu_unwind_stack_user.dwfl_attach_state(cpu_pmu_unwind_stack_user.Dwfl*, cpu_pmu_unwind_stack_user.Elf*, int pid, const(cpu_pmu_unwind_stack_user.DwflThreadCallbacks)*, void* arg) nothrow @nogc
dwfl_attach_state
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*,
(struct) cpu_pmu_unwind_stack_user.Elf
Elf
*, int
(parameter) int pid
pid
, const(
(struct) cpu_pmu_unwind_stack_user.DwflThreadCallbacks

Dwfl_Thread_Callbacks (elfutils@6f8f78c libdwfl/libdwfl.h:661): field order next_thread, get_thread, memory_read, set_initial_registers, detach, thread_detach.

DwflThreadCallbacks
)*, void*
(parameter) void* arg
arg
);
int
int cpu_pmu_unwind_stack_user.dwfl_getthread_frames(cpu_pmu_unwind_stack_user.Dwfl*, int tid, void* callback, void* arg) nothrow @nogc
dwfl_getthread_frames
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*, int
(parameter) int tid
tid
, void*
(parameter) void* callback
callback
, void*
(parameter) void* arg
arg
);
bool
bool cpu_pmu_unwind_stack_user.dwfl_frame_pc(cpu_pmu_unwind_stack_user.Dwfl_Frame*, ulong* pc, bool* isactivation) nothrow @nogc
dwfl_frame_pc
(
(struct) cpu_pmu_unwind_stack_user.Dwfl_Frame
Dwfl_Frame
*,
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
*
(parameter) ulong* pc
pc
, bool*
(parameter) bool* isactivation
isactivation
);
void
void cpu_pmu_unwind_stack_user.dwfl_thread_state_register_pc(cpu_pmu_unwind_stack_user.Dwfl_Thread*, ulong pc) nothrow @nogc
dwfl_thread_state_register_pc
(
(struct) cpu_pmu_unwind_stack_user.Dwfl_Thread
Dwfl_Thread
*,
(alias) cpu_pmu_unwind_stack_user.Dwarf_Word = ulong
Dwarf_Word
(parameter) ulong pc
pc
);
bool
bool cpu_pmu_unwind_stack_user.dwfl_thread_state_registers(cpu_pmu_unwind_stack_user.Dwfl_Thread*, int firstreg, uint nregs, const(ulong)* regs) nothrow @nogc
dwfl_thread_state_registers
(
(struct) cpu_pmu_unwind_stack_user.Dwfl_Thread
Dwfl_Thread
*, int
(parameter) int firstreg
firstreg
, uint
(parameter) uint nregs
nregs
, const(
(alias) cpu_pmu_unwind_stack_user.Dwarf_Word = ulong
Dwarf_Word
)*
(parameter) const(ulong)* regs
regs
);
int
int cpu_pmu_unwind_stack_user.dwfl_linux_proc_find_elf() nothrow @nogc
dwfl_linux_proc_find_elf
();
int
int cpu_pmu_unwind_stack_user.dwfl_standard_find_debuginfo() nothrow @nogc
dwfl_standard_find_debuginfo
();
} // ---- perf x86-64 register order (arch/x86/include/uapi/asm/perf_regs.h) // The sample_regs_user mask we set selects, in ascending bit order: // AX BX CX DX SI DI BP SP IP (bits 0..8), then R8..R15 (bits 16..23). enum ulong
(constant) ulong cpu_pmu_unwind_stack_user.regsMask = 16712191LU
regsMask
= 0x1FFUL | (0xFFUL << 16); // 17 registers
enum
(enum) cpu_pmu_unwind_stack_user.CapIdx
CapIdx
{
(enum value) cpu_pmu_unwind_stack_user.CapIdx.AX = 0
AX
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.BX = 1
BX
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.CX = 2
CX
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.DX = 3
DX
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.SI = 4
SI
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.DI = 5
DI
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.BP = 6
BP
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.SP = 7
SP
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.IP = 8
IP
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R8 = 9
R8
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R9 = 10
R9
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R10 = 11
R10
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R11 = 12
R11
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R12 = 13
R12
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R13 = 14
R13
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R14 = 15
R14
,
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R15 = 16
R15
}
/// One captured sample: leaf IP, the 17 selected registers (perf order), and /// a copy of the user-stack slab (valid `dyn_size` bytes from `sp` upward). struct
(struct) cpu_pmu_unwind_stack_user.Sample

One captured sample: leaf IP, the 17 selected registers (perf order), and a copy of the user-stack slab (valid dyn_size bytes from sp upward).

Sample
{ ulong
(field) ulong cpu_pmu_unwind_stack_user.Sample.ip
ip
;
int
(field) int cpu_pmu_unwind_stack_user.Sample.tid
tid
;
ulong
(field) ulong cpu_pmu_unwind_stack_user.Sample.regsAbi
regsAbi
;
ulong[17]
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
;
ubyte[]
(field) ubyte[] cpu_pmu_unwind_stack_user.Sample.stack
stack
;
ulong
(field) ulong cpu_pmu_unwind_stack_user.Sample.sp
sp
;
} // The unwind callbacks are C function pointers; a single-threaded probe can // route their context through one global. __gshared
(struct) cpu_pmu_unwind_stack_user.Sample

One captured sample: leaf IP, the 17 selected registers (perf order), and a copy of the user-stack slab (valid dyn_size bytes from sp upward).

Sample
*
(__gshared global) cpu_pmu_unwind_stack_user.Sample* cpu_pmu_unwind_stack_user.gSample
gSample
;
__gshared
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
[64]
(__gshared global) ulong[64] cpu_pmu_unwind_stack_user.gFrames
gFrames
;
__gshared
(alias) object.size_t = ulong
size_t
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
;
extern (C) int
int cpu_pmu_unwind_stack_user.uwNextThread(cpu_pmu_unwind_stack_user.Dwfl* dwfl, void* arg, void** threadArgp) nothrow @nogc
uwNextThread
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*
(parameter) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
, void*
(parameter) void* arg
arg
, void**
(parameter) void** threadArgp
threadArgp
) @nogc nothrow
{ if (*
(parameter) void** threadArgp
threadArgp
!is null)
return 0; *
(parameter) void** threadArgp
threadArgp
=
(parameter) void* arg
arg
;
return
(__gshared global) cpu_pmu_unwind_stack_user.Sample* cpu_pmu_unwind_stack_user.gSample
gSample
.
(field) int cpu_pmu_unwind_stack_user.Sample.tid
tid
;
} extern (C) bool
bool cpu_pmu_unwind_stack_user.uwMemoryRead(cpu_pmu_unwind_stack_user.Dwfl* dwfl, ulong addr, ulong* result, void* arg) nothrow @nogc
uwMemoryRead
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*
(parameter) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
(parameter) ulong addr
addr
,
(alias) cpu_pmu_unwind_stack_user.Dwarf_Word = ulong
Dwarf_Word
*
(parameter) ulong* result
result
, void*
(parameter) void* arg
arg
) @nogc nothrow
{ auto
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
=
(__gshared global) cpu_pmu_unwind_stack_user.Sample* cpu_pmu_unwind_stack_user.gSample
gSample
;
if (
(parameter) ulong addr
addr
>=
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.sp
sp
&&
(parameter) ulong addr
addr
+ 8 <=
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.sp
sp
+
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ubyte[] cpu_pmu_unwind_stack_user.Sample.stack
stack
.
(field) ulong ubyte[].length
length
)
{ *
(parameter) ulong* result
result
= *cast(ulong*)(
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ubyte[] cpu_pmu_unwind_stack_user.Sample.stack
stack
.
(field) ubyte* ubyte[].ptr
ptr
+ (
(parameter) ulong addr
addr
-
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.sp
sp
));
return true; } return false; // outside the captured slab → unwinder stops here } extern (C) bool
bool cpu_pmu_unwind_stack_user.uwSetInitialRegisters(cpu_pmu_unwind_stack_user.Dwfl_Thread* thread, void* arg) nothrow @nogc
uwSetInitialRegisters
(
(struct) cpu_pmu_unwind_stack_user.Dwfl_Thread
Dwfl_Thread
*
(parameter) cpu_pmu_unwind_stack_user.Dwfl_Thread* thread
thread
, void*
(parameter) void* arg
arg
) @nogc nothrow
{ auto
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
=
(__gshared global) cpu_pmu_unwind_stack_user.Sample* cpu_pmu_unwind_stack_user.gSample
gSample
;
// Map perf capture order → DWARF x86-64 register numbers 0..16. with (
(enum) cpu_pmu_unwind_stack_user.CapIdx
CapIdx
)
{
(alias) cpu_pmu_unwind_stack_user.Dwarf_Word = ulong
Dwarf_Word
[17]
(local variable) ulong[17] dw
dw
= [
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.AX = 0
AX
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.DX = 3
DX
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.CX = 2
CX
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.BX = 1
BX
], // dw 0..3
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.SI = 4
SI
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.DI = 5
DI
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.BP = 6
BP
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.SP = 7
SP
], // dw 4..7
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R8 = 9
R8
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R9 = 10
R9
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R10 = 11
R10
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R11 = 12
R11
], // dw 8..11
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R12 = 13
R12
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R13 = 14
R13
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R14 = 15
R14
],
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.R15 = 16
R15
], // dw 12..15
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.IP = 8
IP
], // dw 16 = RIP
];
void cpu_pmu_unwind_stack_user.dwfl_thread_state_register_pc(cpu_pmu_unwind_stack_user.Dwfl_Thread*, ulong pc) nothrow @nogc
dwfl_thread_state_register_pc
(
(parameter) cpu_pmu_unwind_stack_user.Dwfl_Thread* thread
thread
,
(local variable) cpu_pmu_unwind_stack_user.Sample* s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.IP = 8
IP
]);
return
bool cpu_pmu_unwind_stack_user.dwfl_thread_state_registers(cpu_pmu_unwind_stack_user.Dwfl_Thread*, int firstreg, uint nregs, const(ulong)* regs) nothrow @nogc
dwfl_thread_state_registers
(
(parameter) cpu_pmu_unwind_stack_user.Dwfl_Thread* thread
thread
, 0, 17,
(local variable) ulong[17] dw
dw
.
(constant) ulong* ulong[17].ptr = &dw
ptr
);
} } extern (C) int
int cpu_pmu_unwind_stack_user.uwFrameCb(cpu_pmu_unwind_stack_user.Dwfl_Frame* state, void* arg) nothrow @nogc
uwFrameCb
(
(struct) cpu_pmu_unwind_stack_user.Dwfl_Frame
Dwfl_Frame
*
(parameter) cpu_pmu_unwind_stack_user.Dwfl_Frame* state
state
, void*
(parameter) void* arg
arg
) @nogc nothrow
{
(alias) cpu_pmu_unwind_stack_user.Dwarf_Addr = ulong
Dwarf_Addr
(local variable) ulong pc
pc
;
bool
(local variable) bool isActivation
isActivation
;
if (!
bool cpu_pmu_unwind_stack_user.dwfl_frame_pc(cpu_pmu_unwind_stack_user.Dwfl_Frame*, ulong* pc, bool* isactivation) nothrow @nogc
dwfl_frame_pc
(
(parameter) cpu_pmu_unwind_stack_user.Dwfl_Frame* state
state
, &
(local variable) ulong pc
pc
, &
(local variable) bool isActivation
isActivation
))
return 1; // DWARF_CB_ABORT if (!
(local variable) bool isActivation
isActivation
&&
(local variable) ulong pc
pc
)
(local variable) ulong pc
pc
-= 1; // step back into the call instruction for the caller frames
if (
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
<
(__gshared global) ulong[64] cpu_pmu_unwind_stack_user.gFrames
gFrames
.
(constant) ulong ulong[64].length = 64LU
length
)
(__gshared global) ulong[64] cpu_pmu_unwind_stack_user.gFrames
gFrames
[
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
++] =
(local variable) ulong pc
pc
;
return
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
>= 32 ? 1 : 0; // cap depth; DWARF_CB_OK = 0
} // ---- a deliberately deep, frame-pointer-less call chain ------------ __gshared ulong
(__gshared global) ulong cpu_pmu_unwind_stack_user.sink
sink
;
pragma(inline, false) ulong
ulong cpu_pmu_unwind_stack_user.level3(ulong x)
level3
(ulong
(parameter) ulong x
x
)
{ ulong
(local variable) ulong s
s
= 0;
foreach (
(local variable) int i
i
; 0 .. 6000)
(local variable) ulong s
s
+= (
(parameter) ulong x
x
^
(local variable) int i
i
) * (
(local variable) int i
i
+ 1);
return
(local variable) ulong s
s
;
} pragma(inline, false) ulong
ulong cpu_pmu_unwind_stack_user.level2(ulong x)
level2
(ulong
(parameter) ulong x
x
) =>
ulong cpu_pmu_unwind_stack_user.level3(ulong x)
level3
(
(parameter) ulong x
x
) +
ulong cpu_pmu_unwind_stack_user.level3(ulong x)
level3
(
(parameter) ulong x
x
>> 1);
pragma(inline, false) ulong
ulong cpu_pmu_unwind_stack_user.level1(ulong x)
level1
(ulong
(parameter) ulong x
x
) =>
ulong cpu_pmu_unwind_stack_user.level2(ulong x)
level2
(
(parameter) ulong x
x
) ^
ulong cpu_pmu_unwind_stack_user.level2(ulong x)
level2
(
(parameter) ulong x
x
+ 1);
void
void cpu_pmu_unwind_stack_user.workload()
workload
()
{ auto
(local variable) core.time.MonoTimeImpl!(ClockType.normal) deadline
deadline
=
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
.
core.time.MonoTimeImpl!(ClockType.normal) core.time.MonoTimeImpl!(ClockType.normal).currTime() nothrow @nogc @property @trusted

The current time of the system's monotonic clock. This has no relation to the wall clock time, as the wall clock time can be adjusted (e.g. by NTP), whereas the monotonic clock always moves forward. The source of the monotonic time is system-specific.

On Windows, QueryPerformanceCounter is used. On Mac OS X, mach_absolute_time is used, while on other POSIX systems, clock_gettime is used.

Warning: On some systems, the monotonic clock may stop counting when the computer goes to sleep or hibernates. So, the monotonic clock may indicate less time than has actually passed if that occurs. This is known to happen on Mac OS X. It has not been tested whether it occurs on either Windows or Linux.

currTime
+ 400.msecs;
ulong
(local variable) ulong acc
acc
= 0xABCD_1234_5678_9EF0UL;
while (
(struct) core.time.MonoTimeImpl!(ClockType.normal)
MonoTime
.
core.time.MonoTimeImpl!(ClockType.normal) core.time.MonoTimeImpl!(ClockType.normal).currTime() nothrow @nogc @property @trusted

The current time of the system's monotonic clock. This has no relation to the wall clock time, as the wall clock time can be adjusted (e.g. by NTP), whereas the monotonic clock always moves forward. The source of the monotonic time is system-specific.

On Windows, QueryPerformanceCounter is used. On Mac OS X, mach_absolute_time is used, while on other POSIX systems, clock_gettime is used.

Warning: On some systems, the monotonic clock may stop counting when the computer goes to sleep or hibernates. So, the monotonic clock may indicate less time than has actually passed if that occurs. This is known to happen on Mac OS X. It has not been tested whether it occurs on either Windows or Linux.

currTime
<
(local variable) core.time.MonoTimeImpl!(ClockType.normal) deadline
deadline
)
(local variable) ulong acc
acc
+=
ulong cpu_pmu_unwind_stack_user.level1(ulong x)
level1
(
(local variable) ulong acc
acc
);
(__gshared global) ulong cpu_pmu_unwind_stack_user.sink
sink
+=
(local variable) ulong acc
acc
;
} /// Resolve a PC to `name+off` for the backtrace print.
(alias) object.string = string
string
string cpu_pmu_unwind_stack_user.symbolize(cpu_pmu_unwind_stack_user.Dwfl* dwfl, ulong pc)

Resolve a PC to name+off for the backtrace print.

symbolize
(
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*
(parameter) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
, ulong
(parameter) ulong pc
pc
)
{ auto
(local variable) cpu_pmu_unwind_stack_user.Dwfl_Module* mod
mod
= (() @trusted =>
cpu_pmu_unwind_stack_user.Dwfl_Module* cpu_pmu_unwind_stack_user.dwfl_addrmodule(cpu_pmu_unwind_stack_user.Dwfl*, ulong) nothrow @nogc
dwfl_addrmodule
(
(parameter) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
(parameter) ulong pc
pc
))();
if (
(local variable) cpu_pmu_unwind_stack_user.Dwfl_Module* mod
mod
is null)
return "<no module>";
(alias) cpu_pmu_unwind_stack_user.GElf_Off = ulong
GElf_Off
(local variable) ulong off
off
;
(struct) cpu_pmu_unwind_stack_user.GElf_Sym
GElf_Sym
(local variable) cpu_pmu_unwind_stack_user.GElf_Sym sym
sym
;
const
(local variable) const(char*) namez
namez
= (() @trusted =>
const(char)* cpu_pmu_unwind_stack_user.dwfl_module_addrinfo(cpu_pmu_unwind_stack_user.Dwfl_Module*, ulong, ulong*, cpu_pmu_unwind_stack_user.GElf_Sym*, uint*, cpu_pmu_unwind_stack_user.Elf**, ulong*) nothrow @nogc
dwfl_module_addrinfo
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl_Module* mod
mod
,
(parameter) ulong pc
pc
, &
(local variable) ulong off
off
, &
(local variable) cpu_pmu_unwind_stack_user.GElf_Sym sym
sym
, null, null, null))();
if (
(local variable) const(char*) namez
namez
is null)
return "<unknown>"; import
(package) std
std
.
(module) std.conv

A one-stop shop for converting values from one type to another.

Category Functions
Generic asOriginalType castFrom parse to toChars bitCast
Strings text wtext dtext writeText writeWText writeDText hexString
Numeric octal roundTo signed unsigned
Exceptions ConvException ConvOverflowException

Source

std/conv.d

@copyrightCopyright The D Language Foundation 2007-.@licenseBoost License 1.0.@authorsWalter Bright, Andrei Alexandrescu, Shin Fujishiro, Adam D. Ruppe, Kenji Hara
conv
:
(alias template) to = std.conv.to(T)

The to template converts a value from one type _to another. The source type is deduced and the target type must be specified, for example the expression to!int(42.0) converts the number 42 from double _to int. The conversion is "safe", i.e., it checks for overflow; to!int(4.2e10) would throw the ConvOverflowException exception. Overflow checks are only inserted when necessary, e.g., to!double(42) does not do any checking because any int fits in a double.

Conversions from string _to numeric types differ from the C equivalents atoi() and atol() by checking for overflow and not allowing whitespace.

For conversion of strings _to signed types, the grammar recognized is: $(PRE $(I Integer): $(I Sign UnsignedInteger) $(I UnsignedInteger) $(I Sign): $(B +) $(B -))

For conversion _to unsigned types, the grammar recognized is: $(PRE $(I UnsignedInteger): $(I DecimalDigit) $(I DecimalDigit) $(I UnsignedInteger))

to
;
return
inout(char)[] std.string.fromStringz!char(return scope inout(char)* cString) pure nothrow @nogc @system
@paramcString A null-terminated c-style string.@returns

A D-style array of char, wchar or dchar referencing the same string. The returned array will retain the same type qualifiers as the input.

Important Note: The returned array is a slice of the original buffer. The original data is not changed and not copied.

fromStringz
(
(local variable) const(char*) namez
namez
).
string object.idup!(const(char))(const(char)[] a) pure nothrow @property @safe

Provide the .idup array property, which creates an immutable duplicate.

idup
~ "+0x" ~
(local variable) ulong off
off
.
string std.conv.to!string.to!(ulong, int)(ulong __param_0, int __param_1) pure @safe

The to template converts a value from one type to another. The source type is deduced and the target type must be specified, for example the expression to`!int(42.0)` converts the number 42 from `double` to `int`. The conversion is "safe", i.e., it checks for overflow; to!int(4.2e10) would throw the ConvOverflowException exception. Overflow checks are only inserted when necessary, e.g., ``to!double(42) does not do any checking because any int fits in a double.

Conversions from string to numeric types differ from the C equivalents atoi() and atol() by checking for overflow and not allowing whitespace.

For conversion of strings to signed types, the grammar recognized is: Integer: Sign UnsignedInteger UnsignedInteger Sign: + -

For conversion to unsigned types, the grammar recognized is: UnsignedInteger: DecimalDigit DecimalDigit UnsignedInteger

Examples

Converting a value to its own type (useful mostly for generic code) simply returns its argument.

int a = 42;
int b = to!int(a);
double c = to!double(3.14); // c is double with value 3.14

Converting among numeric types is a safe way to cast them around.

Conversions from floating-point types to integral types allow loss of precision (the fractional part of a floating-point number). The conversion is truncating towards zero, the same way a cast would truncate. (To round a floating point value when casting to an integral, use roundTo.)

import std.exception : assertThrown;

int a = 420;
assert(to!long(a) == a);
assertThrown!ConvOverflowException(to!byte(a));

assert(to!int(4.2e6) == 4200000);
assertThrown!ConvOverflowException(to!uint(-3.14));
assert(to!uint(3.14) == 3);
assert(to!uint(3.99) == 3);
assert(to!int(-3.99) == -3);

When converting strings to numeric types, note that D hexadecimal and binary literals are not handled. Neither the prefixes that indicate the base, nor the horizontal bar used to separate groups of digits are recognized. This also applies to the suffixes that indicate the type.

To work around this, you can specify a radix for conversions involving numbers.

auto str = to!string(42, 16);
assert(str == "2A");
auto i = to!int(str, 16);
assert(i == 42);

Conversions from integral types to floating-point types always succeed, but might lose accuracy. The largest integers with a predecessor representable in floating-point format are 2^24-1 for float, 2^53-1 for double, and 2^64-1 for real (when real is 80-bit, e.g. on Intel machines).

// 2^24 - 1, largest proper integer representable as float
int a = 16_777_215;
assert(to!int(to!float(a)) == a);
assert(to!int(to!float(-a)) == -a);

Conversion from string types to char types enforces the input to consist of a single code point, and said code point must fit in the target type. Otherwise, ConvException is thrown.

import std.exception : assertThrown;

assert(to!char("a") == 'a');
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
assert(to!wchar("ñ") == 'ñ');
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
assert(to!dchar("😃") == '😃');

// Using wstring or dstring as source type does not affect the result
assert(to!char("a"w) == 'a');
assert(to!char("a"d) == 'a');

// Two code points cannot be converted to a single one
assertThrown(to!char("ab"));

Converting an array to another array type works by converting each element in turn. Associative arrays can be converted to associative arrays as long as keys and values can in turn be converted.

import std.string : split;

int[] a = [1, 2, 3];
auto b = to!(float[])(a);
assert(b == [1.0f, 2, 3]);
string str = "1 2 3 4 5 6";
auto numbers = to!(double[])(split(str));
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
int[string] c;
c["a"] = 1;
c["b"] = 2;
auto d = to!(double[wstring])(c);
assert(d["a"w] == 1 && d["b"w] == 2);

Conversions operate transitively, meaning that they work on arrays and associative arrays of any complexity.

This conversion works because to`!short` applies to an `int`, to!wstring applies to a string, to`!string` applies to a `double`, and to!(double[]) applies to an int[]. The conversion might throw an exception because ``to!short might fail the range check.

int[string][double[int[]]] a;
auto b = to!(short[wstring][string[double[]]])(a);

Object-to-object conversions by dynamic casting throw exception when the source is non-null and the target is null.

import std.exception : assertThrown;
// Testing object conversions
class A {}
class B : A {}
class C : A {}
A a1 = new A, a2 = new B, a3 = new C;
assert(to!B(a2) is a2);
assert(to!C(a3) is a3);
assertThrown!ConvException(to!B(a3));

Stringize conversion from all types is supported.

  • String to string conversion works for any two string types having (char, wchar, dchar) character widths and any combination of qualifiers (mutable, const, or immutable).

  • Converts array (other than strings) to string. Each element is converted by calling ``to!T.

  • Associative array to string conversion. Each element is converted by calling ``to!T.

  • Object to string conversion calls toString against the object or returns "null" if the object is null.

  • Struct to string conversion calls toString against the struct if it is defined.

  • For structs that do not define toString, the conversion to string produces the list of fields.

  • Enumerated types are converted to strings as their symbolic names.

  • Boolean values are converted to "true" or "false".

  • char, wchar, dchar to a string type.

  • Unsigned or signed integers to strings.

    special case

    : Convert integral value to string in radix radix. radix must be a value from 2 to 36. value is treated as a signed value only if radix is 10. The characters A through Z are used to represent values 10 through 36 and their case is determined by the letterCase parameter.

  • All floating point types to all string types.

  • Pointer to string conversions convert the pointer to a size_t value. If pointer is char*, treat it as C-style strings. In that case, this function is @system.

See formatValue on how toString should be defined.

// Conversion representing dynamic/static array with string
long[] a = [ 1, 3, 5 ];
assert(to!string(a) == "[1, 3, 5]");

// Conversion representing associative array with string
int[string] associativeArray = ["0":1, "1":2];
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
       to!string(associativeArray) == `["1":2, "0":1]`);

// char* to string conversion
assert(to!string(cast(char*) null) == "");
assert(to!string("foo\0".ptr) == "foo");

// Conversion reinterpreting void array to string
auto w = "abcx"w;
const(void)[] b = w;
assert(b.length == 8);

auto c = to!(wchar[])(b);
assert(c == "abcx");

Strings can be converted to enum types. The enum member with the same name as the input string is returned. The comparison is case-sensitive.

A ConvException is thrown if the enum does not have the specified member.

import std.exception : assertThrown;

enum E { a, b, c }
assert(to!E("a") == E.a);
assert(to!E("b") == E.b);
assertThrown!ConvException(to!E("A"));
to
!
(alias) object.string = string
string
(16);
} int
int cpu_pmu_unwind_stack_user.run()
run
()
{ const
(local variable) const(ulong) pageSize
pageSize
= cast(
(alias) object.size_t = ulong
size_t
)
long core.sys.posix.unistd.sysconf(int) nothrow @nogc @trusted
sysconf
(
(enum value) core.sys.posix.unistd._SC_PAGESIZE = 30
_SC_PAGESIZE
);
enum
(constant) int cpu_pmu_unwind_stack_user.run.dataPages = 256
dataPages
= 256;
const
(local variable) const(ulong) dataSize
dataSize
=
(constant) int cpu_pmu_unwind_stack_user.run.dataPages = 256
dataPages
*
(local variable) const(ulong) pageSize
pageSize
;
const
(local variable) const(ulong) mmapSize
mmapSize
= (1 +
(constant) int cpu_pmu_unwind_stack_user.run.dataPages = 256
dataPages
) *
(local variable) const(ulong) pageSize
pageSize
;
enum
(constant) uint cpu_pmu_unwind_stack_user.run.stackBytes = 8192u
stackBytes
= 8192u;
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware event_id to monitor via a performance monitoring event:

@sample_max_stack: Max number of frame pointers in a callchain, should be < /proc/sys/kernel/perf_event_max_stack

perf_event_attr
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) uint core.sys.linux.perf_event.perf_event_attr.size

Size of the attr structure, for fwd/bwd compat.

size
=
(struct) core.sys.linux.perf_event.perf_event_attr

Hardware event_id to monitor via a performance monitoring event:

@sample_max_stack: Max number of frame pointers in a callchain, should be < /proc/sys/kernel/perf_event_max_stack

perf_event_attr
.
(constant) ulong core.sys.linux.perf_event.perf_event_attr.sizeof = 112LU
sizeof
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) uint core.sys.linux.perf_event.perf_event_attr.type

Major type: hardware/software/tracepoint/etc.

type
=
(enum) core.sys.linux.perf_event.perf_type_id

attr.type

perf_type_id
.
(enum value) core.sys.linux.perf_event.perf_type_id.PERF_TYPE_HARDWARE = 0
PERF_TYPE_HARDWARE
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.config

Type specific configuration information.

config
=
(enum) core.sys.linux.perf_event.perf_hw_id

Generalized performance event event_id types, used by the attr.event_id parameter of the sys_perf_event_open() syscall:

perf_hw_id
.
(enum value) core.sys.linux.perf_event.perf_hw_id.PERF_COUNT_HW_CPU_CYCLES = 0
PERF_COUNT_HW_CPU_CYCLES
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.sample_type
sample_type
=
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_IP = 1u
PERF_SAMPLE_IP
|
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_TID = 2u
PERF_SAMPLE_TID
|
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_TIME = 4u
PERF_SAMPLE_TIME
|
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_REGS_USER = 4096u
PERF_SAMPLE_REGS_USER
|
(enum) core.sys.linux.perf_event.perf_event_sample_format

Bits that can be set in attr.sample_type to request information in the overflow packets.

perf_event_sample_format
.
(enum value) core.sys.linux.perf_event.perf_event_sample_format.PERF_SAMPLE_STACK_USER = 8192u
PERF_SAMPLE_STACK_USER
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.sample_regs_user

Defines set of user regs to dump on samples. See asm/perf_regs.h for details.

sample_regs_user
=
(constant) ulong cpu_pmu_unwind_stack_user.regsMask = 16712191LU
regsMask
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) uint core.sys.linux.perf_event.perf_event_attr.sample_stack_user

Defines size of the user stack to dump on samples.

sample_stack_user
=
(constant) uint cpu_pmu_unwind_stack_user.run.stackBytes = 8192u
stackBytes
;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.freq(ulong v) pure nothrow @nogc @property @safe
freq
= 1;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
(field) ulong core.sys.linux.perf_event.perf_event_attr.sample_freq
sample_freq
= 1500;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.disabled(ulong v) pure nothrow @nogc @property @safe
disabled
= 1;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.exclude_kernel(ulong v) pure nothrow @nogc @property @safe
exclude_kernel
= 1;
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
.
void core.sys.linux.perf_event.perf_event_attr.exclude_hv(ulong v) pure nothrow @nogc @property @safe
exclude_hv
= 1;
int
(local variable) int fd
fd
= (() @trusted => cast(int)
long core.sys.linux.perf_event.perf_event_open(core.sys.linux.perf_event.perf_event_attr* hw_event, int pid, int cpu, int group_fd, ulong flags) nothrow @nogc
perf_event_open
(&
(local variable) core.sys.linux.perf_event.perf_event_attr attr
attr
, 0, -1, -1, 0))();
if (
(local variable) int fd
fd
< 0)
{
void std.stdio.writefln!char(in char[] fmt) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("SKIP: perf_event_open (stack sampling) failed — "
~ "perf_event_paranoid, seccomp, or no PMU"); return 0; } void*
(local variable) void* base
base
= (() @trusted => mmap(null,
(local variable) const(ulong) mmapSize
mmapSize
,
(constant) int core.sys.posix.sys.mman.PROT_READ = 1
PROT_READ
|
(constant) int core.sys.posix.sys.mman.PROT_WRITE = 2
PROT_WRITE
,
(constant) int core.sys.posix.sys.mman.MAP_SHARED = 1
MAP_SHARED
,
(local variable) int fd
fd
, 0))();
if (
(local variable) void* base
base
is
(constant) void* core.sys.posix.sys.mman.MAP_FAILED = cast(void*)cast(size_t)18446744073709551615LU
MAP_FAILED
)
{
void std.stdio.writefln!char(in char[] fmt) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("SKIP: mmap of perf ring buffer failed");
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) int fd
fd
);
return 0; } auto
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
= cast(
(struct) core.sys.linux.perf_event.perf_event_mmap_page

Structure of the page that can be mapped via mmap

perf_event_mmap_page
*)
(local variable) void* base
base
;
auto
(local variable) ubyte* dataArea
dataArea
= cast(ubyte*)
(local variable) void* base
base
+
(local variable) const(ulong) pageSize
pageSize
;
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(local variable) int fd
fd
, cast(c_ulong)
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_RESET = 9219
PERF_EVENT_IOC_RESET
, 0);
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(local variable) int fd
fd
, cast(c_ulong)
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_ENABLE = 9216

Ioctls that can be done on a perf event fd:

PERF_EVENT_IOC_ENABLE
, 0);
void cpu_pmu_unwind_stack_user.workload()
workload
();
int core.sys.posix.sys.ioctl.ioctl(int __fd, ulong __request, ...) nothrow @nogc
ioctl
(
(local variable) int fd
fd
, cast(c_ulong)
(constant) int core.sys.linux.perf_event.PERF_EVENT_IOC_DISABLE = 9217
PERF_EVENT_IOC_DISABLE
, 0);
const
(local variable) const(ulong) head
head
=
ulong core.atomic.atomicLoad!(MemoryOrder.acq, ulong)(ref return scope const(ulong) val) pure nothrow @nogc @trusted

Loads 'val' from memory and returns it. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.acq, and MemoryOrder.seq.

@paramval The target variable.@returnsThe value of 'val'.
atomicLoad
!(
(enum) core.atomic.MemoryOrder

Specifies the memory ordering semantics of an atomic operation.

@see
MemoryOrder
.
(enum value) core.atomic.MemoryOrder.acq = 2

Hoist-load + hoist-store barrier. Corresponds to LLVM AtomicOrdering.Acquire and C++11/C11 memory_order_acquire.

acq
)(
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
.
(field) ulong core.sys.linux.perf_event.perf_event_mmap_page.data_head

Control data for the mmap() data buffer.

User-space reading the @data_head value should issue an smp_rmb(), after reading this value.

When the mapping is PROT_WRITE the @data_tail value should be written by userspace to reflect the last read data, after issueing an smp_mb() to separate the data read from the ->data_tail store. In this case the kernel will not over-write unread data.

See perf_output_put_handle() for the data ordering.

data_{offset,size} indicate the location and size of the perf record buffer within the mmapped area.

head in the data section

data_head
);
ulong
(local variable) ulong tail
tail
=
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
.
(field) ulong core.sys.linux.perf_event.perf_event_mmap_page.data_tail

user-space written tail

data_tail
;
ubyte[32768]
(local variable) ubyte[32768] rec
rec
;
void
void cpu_pmu_unwind_stack_user.run.ringCopy(ulong pos, ubyte* dst, ulong n) pure nothrow @nogc @trusted
ringCopy
(ulong
(parameter) ulong pos
pos
, ubyte*
(parameter) ubyte* dst
dst
,
(alias) object.size_t = ulong
size_t
(parameter) ulong n
n
) @trusted
{ const
(local variable) const(ulong) o
o
=
(parameter) ulong pos
pos
%
(local variable) const(ulong) dataSize
dataSize
;
if (
(local variable) const(ulong) o
o
+
(parameter) ulong n
n
<=
(local variable) const(ulong) dataSize
dataSize
)
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) ubyte* dst
dst
,
(local variable) ubyte* dataArea
dataArea
+
(local variable) const(ulong) o
o
,
(parameter) ulong n
n
);
else { const
(local variable) const(ulong) first
first
= cast(
(alias) object.size_t = ulong
size_t
)(
(local variable) const(ulong) dataSize
dataSize
-
(local variable) const(ulong) o
o
);
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) ubyte* dst
dst
,
(local variable) ubyte* dataArea
dataArea
+
(local variable) const(ulong) o
o
,
(local variable) const(ulong) first
first
);
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(parameter) ubyte* dst
dst
+
(local variable) const(ulong) first
first
,
(local variable) ubyte* dataArea
dataArea
,
(parameter) ulong n
n
-
(local variable) const(ulong) first
first
);
} }
(struct) cpu_pmu_unwind_stack_user.Sample

One captured sample: leaf IP, the 17 selected registers (perf order), and a copy of the user-stack slab (valid dyn_size bytes from sp upward).

Sample
[]
(local variable) cpu_pmu_unwind_stack_user.Sample[] samples
samples
;
(alias) object.size_t = ulong
size_t
(local variable) ulong nRegsAbiNone
nRegsAbiNone
= 0;
while (
(local variable) ulong tail
tail
<
(local variable) const(ulong) head
head
)
{
(struct) core.sys.linux.perf_event.perf_event_header
perf_event_header
(local variable) core.sys.linux.perf_event.perf_event_header h
h
;
void cpu_pmu_unwind_stack_user.run.ringCopy(ulong pos, ubyte* dst, ulong n) pure nothrow @nogc @trusted
ringCopy
(
(local variable) ulong tail
tail
, cast(ubyte*)&
(local variable) core.sys.linux.perf_event.perf_event_header h
h
,
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(constant) ulong core.sys.linux.perf_event.perf_event_header.sizeof = 8LU
sizeof
);
if (
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) ushort core.sys.linux.perf_event.perf_event_header.size
size
== 0)
break;
(alias) object.size_t = ulong
size_t
(local variable) ulong sz
sz
=
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) ushort core.sys.linux.perf_event.perf_event_header.size
size
;
if (
(local variable) ulong sz
sz
>
(local variable) ubyte[32768] rec
rec
.
(constant) ulong ubyte[32768].length = 32768LU
length
)
(local variable) ulong sz
sz
=
(local variable) ubyte[32768] rec
rec
.
(constant) ulong ubyte[32768].length = 32768LU
length
;
void cpu_pmu_unwind_stack_user.run.ringCopy(ulong pos, ubyte* dst, ulong n) pure nothrow @nogc @trusted
ringCopy
(
(local variable) ulong tail
tail
,
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
,
(local variable) ulong sz
sz
);
(local variable) ulong tail
tail
+=
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) ushort core.sys.linux.perf_event.perf_event_header.size
size
;
if (
(local variable) core.sys.linux.perf_event.perf_event_header h
h
.
(field) uint core.sys.linux.perf_event.perf_event_header.type
type
!=
(enum) core.sys.linux.perf_event.perf_event_type
perf_event_type
.
(enum value) core.sys.linux.perf_event.perf_event_type.PERF_RECORD_SAMPLE = 9
struct {
   struct perf_event_header    header;

   #
   # Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.
   # The advantage of PERF_SAMPLE_IDENTIFIER is that its position
   # is fixed relative to header.
   #

   { u64            id;      } && PERF_SAMPLE_IDENTIFIER
   { u64            ip;      } && PERF_SAMPLE_IP
   { u32            pid, tid; } && PERF_SAMPLE_TID
   { u64            time;     } && PERF_SAMPLE_TIME
   { u64            addr;     } && PERF_SAMPLE_ADDR
   { u64            id;      } && PERF_SAMPLE_ID
   { u64            stream_id;} && PERF_SAMPLE_STREAM_ID
   { u32            cpu, res; } && PERF_SAMPLE_CPU
   { u64            period;   } && PERF_SAMPLE_PERIOD

   { struct read_format    values;      } && PERF_SAMPLE_READ

   { u64            nr,
     u64            ips[nr];  } && PERF_SAMPLE_CALLCHAIN

   #
   # The RAW record below is opaque data wrt the ABI
   #
   # That is, the ABI doesn't make any promises wrt to
   # the stability of its content, it may vary depending
   # on event, hardware, kernel version and phase of
   # the moon.
   #
   # In other words, PERF_SAMPLE_RAW contents are not an ABI.
   #

   { u32            size;
     char                  data[size];}&& PERF_SAMPLE_RAW

   { u64                   nr;
       { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK

    { u64            abi; # enum perf_sample_regs_abi
      u64            regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER

    { u64            size;
      char            data[size];
      u64            dyn_size; } && PERF_SAMPLE_STACK_USER

   { u64            weight;   } && PERF_SAMPLE_WEIGHT
   { u64            data_src; } && PERF_SAMPLE_DATA_SRC
   { u64            transaction; } && PERF_SAMPLE_TRANSACTION
   { u64            abi; # enum perf_sample_regs_abi
     u64            regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
   { u64            phys_addr;} && PERF_SAMPLE_PHYS_ADDR
};
PERF_RECORD_SAMPLE
)
continue; // body: ip(8) pid(4) tid(4) time(8) regsAbi(8) regs[17*8] // stackSize(8) stackData[stackSize] dynSize(8) (() @trusted {
(alias) object.size_t = ulong
size_t
(local variable) ulong o
o
= 8;
(struct) cpu_pmu_unwind_stack_user.Sample

One captured sample: leaf IP, the 17 selected registers (perf order), and a copy of the user-stack slab (valid dyn_size bytes from sp upward).

Sample
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
;
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.ip
ip
= *cast(ulong*)(
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
);
(local variable) ulong o
o
+= 8;
(local variable) ulong o
o
+= 4; // pid
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) int cpu_pmu_unwind_stack_user.Sample.tid
tid
= *cast(int*)(
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
);
(local variable) ulong o
o
+= 4;
(local variable) ulong o
o
+= 8; // time
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.regsAbi
regsAbi
= *cast(ulong*)(
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
);
(local variable) ulong o
o
+= 8;
if (
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.regsAbi
regsAbi
== 0)
{
(local variable) ulong nRegsAbiNone
nRegsAbiNone
++;
return; }
void* core.stdc.string.memcpy(return scope void* s1, scope const(void*) s2, ulong n) pure nothrow @nogc
memcpy
(
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
.
(constant) ulong* ulong[17].ptr = &s.regs
ptr
,
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
, 17 * 8);
(local variable) ulong o
o
+= 17 * 8;
const
(local variable) const(ulong) stackSize
stackSize
= *cast(ulong*)(
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
);
(local variable) ulong o
o
+= 8;
const
(local variable) const(ulong) dynSize
dynSize
= *cast(ulong*)(
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
+
(local variable) const(ulong) stackSize
stackSize
);
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.sp
sp
=
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum) cpu_pmu_unwind_stack_user.CapIdx
CapIdx
.
(enum value) cpu_pmu_unwind_stack_user.CapIdx.SP = 7
SP
];
const
(local variable) const(ulong) valid
valid
=
(local variable) const(ulong) dynSize
dynSize
<
(local variable) const(ulong) stackSize
stackSize
?
(local variable) const(ulong) dynSize
dynSize
:
(local variable) const(ulong) stackSize
stackSize
;
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ubyte[] cpu_pmu_unwind_stack_user.Sample.stack
stack
= (
(local variable) ubyte[32768] rec
rec
.
(constant) ubyte* ubyte[32768].ptr = &rec
ptr
+
(local variable) ulong o
o
)[0 .. cast(
(alias) object.size_t = ulong
size_t
)
(local variable) const(ulong) valid
valid
].
ubyte[] object.dup!ubyte(const(ubyte)[] a) pure nothrow @property @safe
dup
;
(local variable) cpu_pmu_unwind_stack_user.Sample[] samples
samples
~=
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
;
})(); }
void core.atomic.atomicStore!(MemoryOrder.rel, ulong, const(ulong))(ref ulong val, const(ulong) newval) pure nothrow @nogc @trusted

Writes 'newval' into 'val'. The memory barrier specified by 'ms' is applied to the operation, which is fully sequenced by default. Valid memory orders are MemoryOrder.raw, MemoryOrder.rel, and MemoryOrder.seq.

@paramval The target variable.@paramnewval The value to store.
atomicStore
!(
(enum) core.atomic.MemoryOrder

Specifies the memory ordering semantics of an atomic operation.

@see
MemoryOrder
.
(enum value) core.atomic.MemoryOrder.rel = 3

Sink-load + sink-store barrier. Corresponds to LLVM AtomicOrdering.Release and C++11/C11 memory_order_release.

rel
)(
(local variable) core.sys.linux.perf_event.perf_event_mmap_page* meta
meta
.
(field) ulong core.sys.linux.perf_event.perf_event_mmap_page.data_tail

user-space written tail

data_tail
,
(local variable) const(ulong) head
head
);
(() @trusted =>
int core.sys.posix.sys.mman.munmap(void*, ulong) nothrow @nogc
munmap
(
(local variable) void* base
base
,
(local variable) const(ulong) mmapSize
mmapSize
))();
int core.sys.posix.unistd.close(int) nothrow @nogc @trusted
close
(
(local variable) int fd
fd
);
void std.stdio.writefln!(char, ulong, ulong)(in char[] fmt, ulong __param_1, ulong __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("captured: %d samples with REGS_USER+STACK_USER "
~ "(%d had ABI_NONE, no user regs)",
(local variable) cpu_pmu_unwind_stack_user.Sample[] samples
samples
.
(field) ulong cpu_pmu_unwind_stack_user.Sample[].length
length
,
(local variable) ulong nRegsAbiNone
nRegsAbiNone
);
if (
(local variable) cpu_pmu_unwind_stack_user.Sample[] samples
samples
.
(field) ulong cpu_pmu_unwind_stack_user.Sample[].length
length
== 0)
{
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("note: no register/stack samples captured — the ring path ran; "
~ "nothing to unwind"); return 0; } // ---- set up libdwfl module model --------------------------------- __gshared
(struct) cpu_pmu_unwind_stack_user.DwflCallbacks

Dwfl_Callbacks (find_elf, find_debuginfo, section_address, debuginfo_path).

DwflCallbacks
(__gshared global) cpu_pmu_unwind_stack_user.DwflCallbacks cpu_pmu_unwind_stack_user.run.cb
cb
;
(__gshared global) cpu_pmu_unwind_stack_user.DwflCallbacks cpu_pmu_unwind_stack_user.run.cb
cb
.
(field) void* cpu_pmu_unwind_stack_user.DwflCallbacks.find_elf
find_elf
= (() @trusted => cast(void*)&
int cpu_pmu_unwind_stack_user.dwfl_linux_proc_find_elf() nothrow @nogc
dwfl_linux_proc_find_elf
)();
(__gshared global) cpu_pmu_unwind_stack_user.DwflCallbacks cpu_pmu_unwind_stack_user.run.cb
cb
.
(field) void* cpu_pmu_unwind_stack_user.DwflCallbacks.find_debuginfo
find_debuginfo
= (() @trusted => cast(void*)&
int cpu_pmu_unwind_stack_user.dwfl_standard_find_debuginfo() nothrow @nogc
dwfl_standard_find_debuginfo
)();
(struct) cpu_pmu_unwind_stack_user.Dwfl
Dwfl
*
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
= (() @trusted =>
cpu_pmu_unwind_stack_user.Dwfl* cpu_pmu_unwind_stack_user.dwfl_begin(const(cpu_pmu_unwind_stack_user.DwflCallbacks)*) nothrow @nogc
dwfl_begin
(&
(__gshared global) cpu_pmu_unwind_stack_user.DwflCallbacks cpu_pmu_unwind_stack_user.run.cb
cb
))();
if (
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
is null
|| (() @trusted =>
int cpu_pmu_unwind_stack_user.dwfl_linux_proc_report(cpu_pmu_unwind_stack_user.Dwfl*, int pid) nothrow @nogc
dwfl_linux_proc_report
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
int core.sys.posix.unistd.getpid() nothrow @nogc @trusted
getpid
()))() != 0
|| (() @trusted =>
int cpu_pmu_unwind_stack_user.dwfl_report_end(cpu_pmu_unwind_stack_user.Dwfl*, void* removed, void* arg) nothrow @nogc
dwfl_report_end
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
, null, null))() != 0)
{
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
("note: libdwfl module reporting failed — capture verified; "
~ "unwind skipped"); return 0; } // Pick a sample whose leaf IP lands in level3 (the deepest frame) so the // backtrace is a stable demonstration; fall back to the first sample.
(struct) cpu_pmu_unwind_stack_user.Sample

One captured sample: leaf IP, the 17 selected registers (perf order), and a copy of the user-stack slab (valid dyn_size bytes from sp upward).

Sample
*
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
= &
(local variable) cpu_pmu_unwind_stack_user.Sample[] samples
samples
[0];
foreach (ref
(parameter) cpu_pmu_unwind_stack_user.Sample s
s
;
(local variable) cpu_pmu_unwind_stack_user.Sample[] samples
samples
)
{ auto
(local variable) string nm
nm
=
string cpu_pmu_unwind_stack_user.symbolize(cpu_pmu_unwind_stack_user.Dwfl* dwfl, ulong pc)

Resolve a PC to name+off for the backtrace print.

symbolize
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.ip
ip
);
import
(package) std
std
.
(module) std.algorithm

This package implements generic algorithms oriented towards the processing of sequences. Sequences processed by these functions define range-based interfaces. See also Reference on ranges and tutorial on ranges.

Algorithms are categorized into the following submodules:

Submodule Functions

| Searching | all any balancedParens boyerMooreFinder canFind commonPrefix count countUntil endsWith find findAdjacent findAmong findSkip findSplit findSplitAfter findSplitBefore minCount maxCount minElement maxElement minIndex maxIndex minPos maxPos skipOver startsWith until |

| Comparison | among castSwitch clamp cmp either equal isPermutation isSameLength levenshteinDistance levenshteinDistanceAndPath max min mismatch predSwitch |

| Iteration | cache cacheBidirectional chunkBy cumulativeFold each filter filterBidirectional fold group joiner map mean permutations reduce splitWhen splitter substitute sum uniq |

| Sorting | completeSort isPartitioned isSorted isStrictlyMonotonic ordered strictlyOrdered makeIndex merge multiSort nextEvenPermutation nextPermutation nthPermutation partialSort partition partition3 schwartzSort sort topN topNCopy topNIndex |

| Set operations (setops) | cartesianProduct largestPartialIntersection largestPartialIntersectionWeighted multiwayMerge multiwayUnion setDifference setIntersection setSymmetricDifference |

| Mutation | bringToFront copy fill initializeAll move moveAll moveSome moveEmplace moveEmplaceAll moveEmplaceSome remove reverse strip stripLeft stripRight swap swapRanges uninitializedFill |

Many functions in this package are parameterized with a predicate. The predicate may be any suitable callable type (a function, a delegate, a functor, or a lambda), or a compile-time string. The string may consist of any legal D expression that uses the symbol a (for unary functions) or the symbols a and b (for binary functions). These names will NOT interfere with other homonym symbols in user code because they are evaluated in a different context. The default for all binary comparison predicates is "a == b" for unordered operations and "a < b" for ordered operations.

Example

int[] a = ...;
static bool greater(int a, int b)
{
    return a > b;
}
sort!greater(a);           // predicate as alias
sort!((a, b) => a > b)(a); // predicate as a lambda.
sort!"a > b"(a);           // predicate as string
                           // (no ambiguity with array name)
sort(a);                   // no predicate, "a < b" is implicit

Source

std/algorithm/package.d

@copyrightAndrei Alexandrescu 2008-.@licenseBoost License 1.0.@authorsAndrei Alexandrescu
algorithm
:
(alias template) canFind = std.algorithm.searching.canFind(alias pred = "a == b")

Convenience function. Like find, but only returns whether or not the search was successful.

For more information about pred see $(LREF find).

See_Also: $(REF among, std,algorithm,comparison) for checking a value against multiple arguments.

canFind
;
if (
(local variable) string nm
nm
.
bool std.algorithm.searching.canFind!().canFind!(string, string)(string haystack, scope string needle) pure nothrow @nogc @safe

Convenience function. Like find, but only returns whether or not the search was successful.

For more information about pred see find.

Examples

const arr = [0, 1, 2, 3];
assert(canFind(arr, 2));
assert(!canFind(arr, 4));

// find one of several needles
assert(arr.canFind(3, 2));
assert(arr.canFind(3, 2) == 2); // second needle found
assert(arr.canFind([1, 3], 2) == 2);

assert(canFind(arr, [1, 2], [2, 3]));
assert(canFind(arr, [1, 2], [2, 3]) == 1);
assert(canFind(arr, [1, 7], [2, 3]));
assert(canFind(arr, [1, 7], [2, 3]) == 2);
assert(!canFind(arr, [1, 3], [2, 4]));
assert(canFind(arr, [1, 3], [2, 4]) == 0);

Example using a custom predicate. Note that the needle appears as the second argument of the predicate.

auto words = [
    "apple",
    "beeswax",
    "cardboard"
];
assert(!canFind(words, "bees"));
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));

Search for multiple items in an array of items (search for needles in an array of haystacks)

string s1 = "aaa111aaa";
string s2 = "aaa222aaa";
string s3 = "aaa333aaa";
string s4 = "aaa444aaa";
const hay = [s1, s2, s3, s4];
assert(hay.canFind!(e => e.canFind("111", "222")));
@see

among for checking a value against multiple arguments.

Returns true if and only if needle can be found in range. Performs O(haystack.length) evaluations of pred.

canFind
("level3"))
{
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
= &
(local variable) cpu_pmu_unwind_stack_user.Sample s
s
;
break; } } // ---- Stage 1: prove the capture (registers + stack) --------------- with (
(enum) cpu_pmu_unwind_stack_user.CapIdx
CapIdx
)
void std.stdio.writefln!(char, ulong, string, ulong, ulong, ulong, ulong, ulong)(in char[] fmt, ulong __param_1, string __param_2, ulong __param_3, ulong __param_4, ulong __param_5, ulong __param_6, ulong __param_7) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("\nchosen sample: leaf IP 0x%x (%s)\n"
~ " regs ABI=%d RIP=0x%x RSP=0x%x RBP=0x%x captured stack=%d bytes",
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.ip
ip
,
string cpu_pmu_unwind_stack_user.symbolize(cpu_pmu_unwind_stack_user.Dwfl* dwfl, ulong pc)

Resolve a PC to name+off for the backtrace print.

symbolize
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.ip
ip
),
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ulong cpu_pmu_unwind_stack_user.Sample.regsAbi
regsAbi
,
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.IP = 8
IP
],
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.SP = 7
SP
],
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ulong[17] cpu_pmu_unwind_stack_user.Sample.regs
regs
[
(enum value) cpu_pmu_unwind_stack_user.CapIdx.BP = 6
BP
],
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) ubyte[] cpu_pmu_unwind_stack_user.Sample.stack
stack
.
(field) ulong ubyte[].length
length
);
// ---- Stage 2: attempt the full in-process CFI unwind --------------
(__gshared global) cpu_pmu_unwind_stack_user.Sample* cpu_pmu_unwind_stack_user.gSample
gSample
=
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
;
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
= 0;
__gshared
(struct) cpu_pmu_unwind_stack_user.DwflThreadCallbacks

Dwfl_Thread_Callbacks (elfutils@6f8f78c libdwfl/libdwfl.h:661): field order next_thread, get_thread, memory_read, set_initial_registers, detach, thread_detach.

DwflThreadCallbacks
(__gshared global) cpu_pmu_unwind_stack_user.DwflThreadCallbacks cpu_pmu_unwind_stack_user.run.tcb
tcb
;
(__gshared global) cpu_pmu_unwind_stack_user.DwflThreadCallbacks cpu_pmu_unwind_stack_user.run.tcb
tcb
.
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.next_thread
next_thread
= (() @trusted => cast(void*)&
int cpu_pmu_unwind_stack_user.uwNextThread(cpu_pmu_unwind_stack_user.Dwfl* dwfl, void* arg, void** threadArgp) nothrow @nogc
uwNextThread
)();
(__gshared global) cpu_pmu_unwind_stack_user.DwflThreadCallbacks cpu_pmu_unwind_stack_user.run.tcb
tcb
.
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.memory_read
memory_read
= (() @trusted => cast(void*)&
bool cpu_pmu_unwind_stack_user.uwMemoryRead(cpu_pmu_unwind_stack_user.Dwfl* dwfl, ulong addr, ulong* result, void* arg) nothrow @nogc
uwMemoryRead
)();
(__gshared global) cpu_pmu_unwind_stack_user.DwflThreadCallbacks cpu_pmu_unwind_stack_user.run.tcb
tcb
.
(field) void* cpu_pmu_unwind_stack_user.DwflThreadCallbacks.set_initial_registers
set_initial_registers
= (() @trusted => cast(void*)&
bool cpu_pmu_unwind_stack_user.uwSetInitialRegisters(cpu_pmu_unwind_stack_user.Dwfl_Thread* thread, void* arg) nothrow @nogc
uwSetInitialRegisters
)();
const
(local variable) const(bool) attached
attached
= (() @trusted =>
bool cpu_pmu_unwind_stack_user.dwfl_attach_state(cpu_pmu_unwind_stack_user.Dwfl*, cpu_pmu_unwind_stack_user.Elf*, int pid, const(cpu_pmu_unwind_stack_user.DwflThreadCallbacks)*, void* arg) nothrow @nogc
dwfl_attach_state
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
, null,
(local variable) cpu_pmu_unwind_stack_user.Sample* chosen
chosen
.
(field) int cpu_pmu_unwind_stack_user.Sample.tid
tid
, &
(__gshared global) cpu_pmu_unwind_stack_user.DwflThreadCallbacks cpu_pmu_unwind_stack_user.run.tcb
tcb
, null))();
int
(local variable) int rc
rc
= -1;
if (
(local variable) const(bool) attached
attached
)
(local variable) int rc
rc
= (() @trusted =>
int cpu_pmu_unwind_stack_user.dwfl_getthread_frames(cpu_pmu_unwind_stack_user.Dwfl*, int tid, void* callback, void* arg) nothrow @nogc
dwfl_getthread_frames
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
(__gshared global) cpu_pmu_unwind_stack_user.Sample* cpu_pmu_unwind_stack_user.gSample
gSample
.
(field) int cpu_pmu_unwind_stack_user.Sample.tid
tid
,
(() @trusted => cast(void*)&
int cpu_pmu_unwind_stack_user.uwFrameCb(cpu_pmu_unwind_stack_user.Dwfl_Frame* state, void* arg) nothrow @nogc
uwFrameCb
)(), null))();
if (
(local variable) const(bool) attached
attached
&&
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
> 0)
{
void std.stdio.writefln!(char, ulong)(in char[] fmt, ulong __param_1) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("\nDWARF-CFI backtrace (%d frames, frame pointers OMITTED — "
~ "so this came purely from .eh_frame/.debug_frame CFI):",
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
);
foreach (
(parameter) ulong i
i
,
(parameter) ulong pc
pc
;
(__gshared global) ulong[64] cpu_pmu_unwind_stack_user.gFrames
gFrames
[0 ..
(__gshared global) ulong cpu_pmu_unwind_stack_user.gNFrames
gNFrames
])
void std.stdio.writefln!(char, ulong, ulong, string)(in char[] fmt, ulong __param_1, ulong __param_2, string __param_3) @safe

Equivalent to writef(fmt, args, '\n').

writefln
(" #%-2d 0x%x %s",
(local variable) ulong i
i
,
(local variable) ulong pc
pc
,
string cpu_pmu_unwind_stack_user.symbolize(cpu_pmu_unwind_stack_user.Dwfl* dwfl, ulong pc)

Resolve a PC to name+off for the backtrace print.

symbolize
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
,
(local variable) ulong pc
pc
));
void std.stdio.writeln!string(string __param_0) @safe

Equivalent to write(args, '\n'). Calling writeln without arguments is valid and just prints a newline to the standard output.

Example

Reads stdin and writes it to stdout with an argument counter.

import std.stdio;

void main()
{
    string line;

    for (size_t count = 0; (line = readln) !is null; count++)
    {
         writeln("Input ", count, ": ", line);
    }
}
@paramargs the items to write to stdout@throwsIn case of an I/O error, throws an StdioException.
writeln
(" (dwfl_getthread_frames drove the unwind; memory_read served "
~ "the captured STACK_USER slab, set_initial_registers the REGS_USER set.)"); } else {
void std.stdio.writefln!(char, const(bool), int)(in char[] fmt, const(bool) __param_1, int __param_2) @safe

Equivalent to writef(fmt, args, '\n').

writefln
("\nnote: in-process dwfl unwind did not complete "
~ "(attach=%s, rc=%d) — the CAPTURE is verified above; the unwind API " ~ "path (dwfl_attach_state → Dwfl_Thread_Callbacks → " ~ "dwfl_getthread_frames → dwfl_frame_pc) is grounded in " ~ "docs/research/cpu-pmu/elfutils.md by source-reading.",
(local variable) const(bool) attached
attached
,
(local variable) int rc
rc
);
} (() @trusted =>
void cpu_pmu_unwind_stack_user.dwfl_end(cpu_pmu_unwind_stack_user.Dwfl*) nothrow @nogc
dwfl_end
(
(local variable) cpu_pmu_unwind_stack_user.Dwfl* dwfl
dwfl
))();
return 0; } } int
int D main()
main
()
{ version (
linux
linux
)
{ version (
X86_64
X86_64
)
return
int cpu_pmu_unwind_stack_user.run()
run
();
else { import std.stdio : writefln; writefln("SKIP: this unwind probe's perf→DWARF register map is x86-64-only"); return 0; } } else { import std.stdio : writefln; writefln("SKIP: perf_event sampling is Linux-only"); return 0; } }