core.internal.backtrace.dwarf

Generates a human-readable stack-trace on POSIX targets using DWARF

The common use case for printing a stack trace is when toString is called on a Throwable (see object.d). It will iterate on what is likely to be the default trace handler (see core.runtime : defaultTraceHandler). The class returned by defaultTraceHandler is what ends up calling into this module, through the use of core.internal.traits : externDFunc.

The entry point of this module is traceHandlerOpApplyImpl, and the only really "public" symbol (since all rt symbols are private). In the future, this implementation should probably be made idiomatic, so that it can for example work with attributes.

Resilience: As this module is used for diagnostic, it should handle failures as gracefully as possible. Having the runtime error out on printing the stack trace one is trying to debug would be quite a terrible UX. For this reason, this module works on a "best effort" basis and will sometimes print mangled symbols, or "???" when it cannot do anything more useful.

Source_of_data: This module uses two main sources for generating human-readable data. First, it uses backtrace_symbols to obtain the name of the symbols (functions or methods) associated with the addresses. Since the names are mangled, it will also call into core.demangle, and doesn't need to use any DWARF information for this, however a future extension could make use of the call frame information (See DWARF4 "6.4 Call Frame Information", PDF page 126).

The other piece of data used is the DWARF .debug_line section, which contains the line informations of a program, necessary to associate the instruction address with its (file, line) information.

Since debug lines informations are quite large, they are encoded using a program that is to be fed to a finite state machine. See runStateMachine and readLineNumberProgram for more details.

DWARF_

Version

This module only supports DWARF 3, 4 and 5.

Reference: http://www.dwarfstd.org/

Types 12

structLocation
Fields
const(void) * addressAddress of the instruction for which this location is for.
const(char)[] procedureThe name of the procedure, or function, this address is in.
const(char)[] filePath to the file this location references, relative to `directory`
const(char)[] directoryDirectory where `file` resides
int lineLine within the file that correspond to this `location`.
Methods
void toString(scope void delegate(scope const char[]) sink) constFormat this location into a human-readable string
Fields
private char[1536] buf
private size_t position
Methods
inout(char)[] opSlice() inout return
void reset()
void put(scope const char[] data)Used as `sink` argument to `Location.toString`
aliasRunStateMachineCallback = bool delegate(const(void) * address, LocationInfo info, bool isEndSequence) @nogc nothrow

A callback type for runStateMachine

The callback is called when certain specific opcode are encountered (a.k.a when a complete LocationInfo is encountered). See runStateMachine implementation and the DWARF specs for more detail.

Parameters

addressThe address that the LocationInfo describes
infoThe LocationInfo itself, describing address
isEndSequenceWhether the end of a sequence has been reached
enumDW_LNCT : ushort
path = 1
directoryIndex = 2
timestamp = 3
size = 4
md5 = 5
loUser = 0x2000
hiUser = 0x3fff
enumDW_FORM : ubyte
addr = 1
block2 = 3
block4 = 4
data2 = 5
data4 = 6
data8 = 7
string_ = 8
block = 9
block1 = 10
data1 = 11
flag = 12
sdata = 13
strp = 14
udata = 15
ref_addr = 16
ref1 = 17
ref2 = 18
ref4 = 19
ref8 = 20
ref_udata = 21
indirect = 22
sec_offset = 23
exprloc = 24
flag_present = 25
strx = 26
addrx = 27
ref_sup4 = 28
strp_sup = 29
data16 = 30
line_strp = 31
ref_sig8 = 32
implicit_const = 33
loclistx = 34
rnglistx = 35
ref_sup8 = 36
strx1 = 37
strx2 = 38
strx3 = 39
strx4 = 40
addrx1 = 41
addrx2 = 42
addrx3 = 43
addrx4 = 44
Fields
DW_LNCT type
DW_FORM form
enumStandardOpcode : ubyte
extendedOp = 0
copy = 1
advancePC = 2
advanceLine = 3
setFile = 4
setColumn = 5
negateStatement = 6
setBasicBlock = 7
constAddPC = 8
fixedAdvancePC = 9
setPrologueEnd = 10
setEpilogueBegin = 11
setISA = 12
enumExtendedOpcode : ubyte
endSequence = 1
setAddress = 2
defineFile = 3
setDiscriminator = 4
Fields
const(void) * address
uint operationIndex
uint fileIndex
uint line
uint column
uint isa
uint discriminator
bool isStatement
bool isBasicBlock
bool isEndSequence
bool isPrologueEnd
bool isEpilogueBegin
Fields
int file
int line
Fields
ulong unitLength
ushort dwarfVersion
ubyte addressSize
ubyte segmentSelectorSize
ulong headerLength
ubyte minimumInstructionLength
ubyte maximumOperationsPerInstruction
bool defaultIsStatement
byte lineBase
ubyte lineRange
ubyte opcodeBase
const(ubyte)[] standardOpcodeLengths
Array!(const(char)[]) includeDirectories
Array!SourceFile sourceFiles
const(ubyte)[] program
Fields
const(char)[] file
size_t dirIndex

Functions 10

fnint traceHandlerOpApplyImpl(size_t numFrames, scope const(void) * delegate(size_t) getNthAddress, scope const(char)[] delegate(size_t) getNthFuncName, scope int delegate(ref size_t, ref const(char[])) dg)
fnint processCallstack(Location[] locations, const(ubyte)[] debugLineSectionData, size_t baseAddress, scope int delegate(ref size_t, ref const(char[])) dg)
fnvoid resolveAddresses(const(ubyte)[] debugLineSectionData, Location[] locations, size_t baseAddress) @nogc nothrowResolve the addresses of `locations` using `debugLineSectionData`
fnbool runStateMachine(ref const(LineNumberProgram) lp, scope RunStateMachineCallback callback) @nogc nothrowRun the state machine to generate line number matrix
fnT read(T)(ref const(ubyte)[] buffer) @nogc nothrow
fnconst(char)[] readStringz(ref const(ubyte)[] buffer) @nogc nothrow
fnulong readULEB128(ref const(ubyte)[] buffer) @nogc nothrow
fnlong readSLEB128(ref const(ubyte)[] buffer) @nogc nothrow
fnArray!EntryFormatPair readEntryFormat(ref const(ubyte)[] buffer) @nogc nothrowReads a DWARF v5 directory/file name entry format.
fnLineNumberProgram readLineNumberProgram(ref const(ubyte)[] data) @nogc nothrow