DDB(4)
DDB(4) โ Kernel Interfaces Manual ๐
okay bestie, sit down, hydrate, because we're about to talk about ddb โ the interactive kernel debugger โจ and honestly? she's iconic.
โจ NAME โจ
ddb โ interactive kernel debugger ๐
๐ธ SYNOPSIS ๐ธ
ok so, first things first: to enable kernel debugging facilities, you include:
options KDB
options DDB
and if you want to prevent activation of the debugger on panic(9):
options KDB_UNATTENDED
and if you want a stack trace of the current thread on the console for a panic, add:
options KDB_TRACE
want the numerical value of symbols in addition to the symbolic representation? then define:
options DDB_NUMSYM
and if you want the gdb(1) backend enabled so that remote debugging with kgdb(1) is possible, include:
options GDB
๐ซถ that's the whole menu, no cap.
๐ฆ DESCRIPTION ๐ฆ
the ddb kernel debugger is an interactive debugger with a syntax inspired by gdb(1). if she's linked into the running kernel, you can invoke her locally with the โdebugโ keymap(5) action. she also gets invoked on panic(9) if the debug.debugger_on_panic sysctl(8) MIB variable is set non-zero โ and that's the default, unless you specified the KDB_UNATTENDED option. (yes bestie, she shows up to the party uninvited by default. main character energy.)
the current location is called dot โญ. dot is displayed with a hexadecimal format at a prompt. the commands examine and write update dot to the address of the last line examined or the last location modified, and set next to the address of the next location to be examined or changed. other commands do not change dot, and set next to be the same as dot.
the general command syntax is:
command[/modifier] [addr][,count]
a blank line repeats the previous command from the address next with count 1 and no modifiers. specifying addr sets dot to the address. omitting addr uses dot. a missing count is taken to be 1 for printing commands, or infinity for stack traces ๐. a count of -1 is equivalent to a missing count. options that are supplied but not supported by the given command are usually ignored (she's chill like that).
also! ddb has a pager feature (like the more(1) command) for the output. if an output line exceeds the number set in the lines variable, she displays โ--More--โ and waits for a response. the valid responses for it are:
SPCโ one more pageRETโ one more lineqโ abort the current command, and return to the command input mode
and finally, ddb provides a small (currently 10 items) command history, plus simple emacs-style command line editing capabilities ๐. in addition to the emacs control keys, the usual ANSI arrow keys may be used to browse through the history buffer, and move the cursor within the current line. obsessed.
๐ COMMANDS ๐
๐ examine
examine[/AISabcdghilmorsuxz ...] [addr][,count]
x[/AISabcdghilmorsuxz ...] [addr][,count]
display the addressed locations according to the formats in the modifier. multiple modifier formats display multiple locations. if no format is specified, the last format specified for this command is used.
the format characters are:
bโ look at by bytes (8 bits)hโ look at by half words (16 bits)lโ look at by long words (32 bits)gโ look at by quad words (64 bits)aโ print the location being displayedAโ print the location with a line number if possiblexโ display in unsigned hexzโ display in signed hexoโ display in unsigned octaldโ display in signed decimaluโ display in unsigned decimalrโ display in current radix, signedcโ display low 8 bits as a character. non-printing characters are displayed as an octal escape code (e.g.,โ\000โ)sโ display the null-terminated string at the location. non-printing characters are displayed as octal escapesmโ display in unsigned hex with character dump at the end of each line. the location is also displayed in hex at the beginning of each lineiโ display as an instructionIโ display as an instruction with possible alternate formats depending on the machine. on i386, this selects the alternate format for the instruction decoding (16 bits in a 32-bit code segment and vice versa)Sโ display a symbol name for the pointer stored at the address
โฉ xf
Examine forward: execute an examine command with the last specified parameters to it, except that the next address displayed by it is used as the start address. slay.
โช xb
Examine backward: execute an examine command with the last specified parameters to it, except that the last start address subtracted by the size displayed by it is used as the start address.
๐จ๏ธ print
print[/acdoruxz]
p[/acdoruxz]
print addrs according to the modifier character (as described above for examine). valid formats are: a, x, z, o, d, u, r, and c. if no modifier is specified, the last one specified to it is used. the argument addr can be a string, in which case it is printed as it is. for example:
print/x "eax = " $eax "\necx = " $ecx "\n"
will print like:
eax = xxxxxx
ecx = yyyyyy
periodt ๐
โ๏ธ write
write[/bhl] addr expr1 [expr2 ...]
w[/bhl] addr expr1 [expr2 ...]
write the expressions specified after addr on the command line at succeeding locations starting with addr. the write unit size can be specified in the modifier with a letter b (byte), h (half word) or l (long word) respectively. if omitted, long word is assumed.
โ ๏ธ Warning: since there is no delimiter between expressions, strange things may happen ๐ญ. it is best to enclose each expression in parentheses. fr fr, do it.
๐ set
set $variable [=] expr
set the named variable or register with the value of expr. valid variable names are described below. (iykyk)
๐ break
break[/u] [addr][,count]
b[/u] [addr][,count]
set a break point at addr. if count is supplied, the continue command will not stop at this break point on the first count - 1 times that it is hit. if the break point is set, a break point number is printed with โ#โ. this number can be used in deleting the break point or adding conditions to it.
if the u modifier is specified, this command sets a break point in user address space. without the u option, the address is considered to be in the kernel space, and a wrong space address is rejected with an error message. this modifier can be used only if it is supported by machine dependent routines.
โ ๏ธ Warning: if a user text is shadowed by a normal user space debugger, user space break points may not work correctly. setting a break point at the low-level code paths may also cause strange behavior. ๐
๐๏ธ delete
delete [addr]
d [addr]
delete #number
d #number
delete the specified break point. the break point can be specified by a break point number with โ#โ, or by using the same addr specified in the original break command, or by omitting addr to get the default address of dot.
๐ watch
watch [addr][,size]
set a watchpoint for a region. execution stops when an attempt to modify the region occurs. the size argument defaults to 4. if you specify a wrong space address, the request is rejected with an error message.
โ ๏ธ Warning: attempts to watch wired kernel memory may cause unrecoverable error in some systems such as i386. watchpoints on user addresses work best. ๐ธ
๐ง hwatch
hwatch [addr][,size]
set a hardware watchpoint for a region if supported by the architecture. execution stops when an attempt to modify the region occurs. the size argument defaults to 4.
โ ๏ธ Warning: the hardware debug facilities do not have a concept of separate address spaces like thewatchcommand does. usehwatchfor setting watchpoints on kernel address locations only, and avoid its use on user mode address spaces. no cap.
๐ฎ dhwatch
dhwatch [addr][,size]
delete specified hardware watchpoint.
๐ step
step[/p][,count]
s[/p][,count]
single step count times. if the p modifier is specified, print each instruction at each step. otherwise, only print the last instruction.
โ ๏ธ Warning: depending on machine type, it may not be possible to single-step through some low-level code paths or user space code. on machines with software-emulated single-stepping (e.g., pmax), stepping through code executed by interrupt handlers will probably do the wrong thing. ๐ญ
โถ๏ธ continue
continue[/c]
c[/c]
continue execution until a breakpoint or watchpoint. if the c modifier is specified, count instructions while executing. some machines (e.g., pmax) also count loads and stores.
โ ๏ธ Warning: when counting, the debugger is really silently single-stepping. this means that single-stepping on low-level code may cause strange behavior. ๐
๐ฌ until
until[/p]
stop at the next call or return instruction. if the p modifier is specified, print the call nesting depth and the cumulative instruction count at each call or return. otherwise, only print when the matching return is hit.
โญ๏ธ next
next[/p]
match[/p]
stop at the matching return instruction. if the p modifier is specified, print the call nesting depth and the cumulative instruction count at each call or return. otherwise, only print when the matching return is hit.
๐งต trace
trace[/u] [pid | tid][,count]
t[/u] [pid | tid][,count]
where[/u] [pid | tid][,count]
bt[/u] [pid | tid][,count]
Stack trace ๐. the u option traces user space; if omitted, trace only traces kernel space. the optional argument count is the number of frames to be traced. if count is omitted, all frames are printed.
โ ๏ธ Warning: user space stack trace is valid only if the machine dependent code supports it.
๐ search
search[/bhl] addr value [mask][,count]
search memory for value. the optional count argument limits the search.
๐ชบ findstack
findstack addr
prints the thread address for a thread kernel-mode stack of which contains the specified address. if the thread is not found, search the thread stack cache and prints the cached stack address. otherwise, prints nothing.
okay bestie that's part 1 ๐ keep reading, there's more where that came from โจ
show all procs[/a]/ps[/a]โ the full process info dump ๐ it displays all process information. lowkey there's a catch tho: the process information may not be shown if it isn't supported in the machine, or if the bottom of the stack of the target process isn't in main memory at that time ๐. add theamodifier and it also prints the command line arguments for each process โจshow all trace/alltraceโ shows a stack trace for every thread in the system ๐ like, the whole entire system. no cap.show all ttysโ shows all the TTY's within the system ๐ the output is similar topstat(8), but it also throws in the address of the TTY structure. slay.show all vnetsโ gives you the exact same output as"show vnet"does, except it lists all the virtualized network stacks within the system ๐ฆshow allchainsโ shows the same information as"show lockchain"does, but for every thread in the system ๐show alllocksโ shows all locks that are currently held ๐ > heads up bestie: this command is only available ifwitness(4)is included in the kernel.show allpcpuโ the same as"show pcpu", but for every CPU present in the system ๐ฅshow allrmanโ shows information related with resource management, including interrupt request lines, DMA request lines, I/O ports, I/O memory addresses, and Resource IDs ๐show apicโ dumps data about APIC IDT vector mappings โจshow breaksโ shows the breakpoints you set with the"break"command ๐show bio addrโ shows information about the bio structurestruct biopresent ataddr. peep thesys/bio.hheader file andg_bio(9)for more details on the exact meaning of the structure fields ๐ธshow buffer addrโ shows information about the buf structurestruct bufpresent ataddr. see thesys/buf.hheader file for more details on the exact meaning of the structure fields ๐ฆshow callout addrโ shows information about the callout structurestruct calloutpresent ataddrโญshow cbstatโ shows brief information about the TTY subsystem ๐show cdevโ with no argument, it shows the list of all created cdev's, consisting of the devfs node name andstruct cdevaddress ๐. when an address of cdev is supplied, it shows some internal devfs state of the cdev โจshow conifhkโ lists hooks currently waiting for completion inrun_interrupt_driven_config_hooks()๐show cpusetsโ prints numbered root and assigned CPU affinity sets. seecpuset(2)for more details ๐show cyrixregโ shows registers specific to the Cyrix processor ๐งshow devmapโ prints the contents of the static device mapping table. currently only available on the ARM architecture ๐show domain addrโ prints the protocol domain structurestruct domainat addressaddr. see thesys/domain.hheader file for more details on the exact meaning of the structure fields ๐show ffs [addr]โ shows brief information about the ffs mount at the addressaddr, if that argument is given. otherwise, it provides the summary about each ffs mount ๐ธshow file addrโ shows information about the file structurestruct filepresent at addressaddrโจshow filesโ shows information about every file structure in the system ๐show freepagesโ shows the number of physical pages in each of the free lists ๐show geom [addr]โ if theaddrargument is not given, it displays the entire GEOM topology ๐ฆ. ifaddris given, it displays details about the given GEOM object (class, geom, provider or consumer) ๐show idtโ shows the IDT layout. the first column specifies the IDT vector. the second one is the name of the interrupt/trap handler. those functions are machine dependent ๐งshow igi_list addrโ shows information about the IGMP structurestruct igmp_ifsoftcpresent ataddr๐show inodedeps [addr]โ shows brief information about each inodedep structure. ifaddris given, only inodedeps belonging to the fs located at the supplied address are shown ๐show inpcb addrโ shows information on the IP Control Blockstruct in_pcbpresent ataddr๐ธshow intrโ dumps information about interrupt handlers โจshow intrcntโ dumps the interrupt statistics ๐ฅshow irqsโ shows interrupt lines and their respective kernel threads ๐show jailsโ shows the list ofjail(8)instances. on top of whatjls(8)shows, it also lists kernel internal details ๐show lapicโ shows information from the local APIC registers for this CPU ๐show lock addrโ shows the lock structure. the output format goes like this:class:โ class of the lock. possible types includemutex(9),rmlock(9),rwlock(9),sx(9).name:โ name of the lock.flags:โ flags passed to the lock initialization function.flagsvalues are lock class specific.state:โ current state of a lock.statevalues are lock class specific.owner:โ lock owner.
show lockchain addrโ shows all threads a particular thread at addressaddris waiting on, based on non-spin locks ๐ฆshow lockedbufsโ shows the same information as"show buf", but for every lockedstruct bufobject ๐show lockedvnodsโ lists all locked vnodes in the system ๐show locksโ prints all locks that are currently acquired. > bestie this one is only available ifwitness(4)is included in the kernel ๐show locktreeโ ok she's listed here with literally no description attached, so... mysterious icon energy ๐โจshow mallocโ printsmalloc(9)memory allocator statistics. the output format goes like this:Typeโ specifies a type of memory. it's the same as the description string used while defining the given memory type withMALLOC_DECLARE(9).InUseโ number of memory allocations of the given type, for whichfree(9)has not been called yet.MemUseโ total memory consumed by the given allocation type.Requestsโ number of memory allocation requests for the given memory type.
the same information can be gathered in userspace with "vmstat -m" ๐
show map[/f] addrโ prints the VM map ataddr. if thefmodifier is specified, the complete map is printed ๐show msgbufโ prints the system's message buffer. it's the same output as in the"dmesg"case ๐ธ. it's useful if you got a kernel panic, attached a serial cable to the machine, and want to get the boot messages from before the system hang ๐ญ๐ซถshow mountโ displays short info about all currently mounted file systems ๐ฆshow mount addrโ displays details about the given mount point โจshow object[/f] addrโ prints the VM object ataddr. if thefoption is specified, the complete object is printed ๐show panicโ prints the panic message if it's set ๐show pageโ shows statistics on VM pages ๐show pageqโ shows statistics on VM page queues โญshow pciregsโ prints PCI bus registers. the same information can be gathered in userspace by running"pciconf -lv"๐ฅshow pcpuโ prints the current processor state. the output format goes like this:cpuidโ processor identifier.curthreadโ thread pointer, process identifier and the name of the process.curpcbโ control block pointer.fpcurthreadโ FPU thread pointer.idlethreadโ idle thread pointer.APIC IDโ CPU identifier coming from APIC.currentldtโ LDT pointer.spin locks heldโ names of spin locks held.
show pgrpdumpโ dumps process groups present within the system ๐show proc [addr]โ if no[addr]is specified, it prints information about the current process. otherwise, it shows information about the process at addressaddr๐show procvmโ shows the process virtual memory layout ๐show protosw addrโ prints the protocol switch structurestruct protoswat addressaddr๐ฆshow registers[/u]โ displays the register set. if theumodifier is specified, it displays user registers instead of kernel registers, or the currently saved one ๐
Warning: the support of the u modifier depends on the machine. if it's not supported, incorrect information will be displayed ๐
show rman addrโ shows the resource manager objectstruct rmanat addressaddr. addresses of particular pointers can be gathered with the"show allrman"command ๐show rtcโ shows the real time clock value. useful for long debugging sessions โฐโจshow sleepchainโ deprecated ๐ซ it's now an alias forshow lockchain.show sleepq/show sleepqueueโ both commands provide the exact same functionality ๐ they show the sleepqueuestruct sleepqueuestructure. sleepqueues are used within the FreeBSD kernel to implement sleepable synchronization primitives (thread holding a lock might sleep or be context switched), which at the time of writing are:condvar(9),sx(9)and the standardmsleep(9)interface ๐ธshow sockbuf addr/show socket addrโ those commands printstruct sockbufandstruct socketobjects placed ataddr. the output consists of all values present in the structures mentioned. for exact interpretation and more details, visit thesys/socket.hheader file ๐ฆshow sysregsโ shows system registers (e.g.,cr0-4on i386.) not present on some platforms ๐show tcpcb addrโ prints the TCP control blockstruct tcpcblying at addressaddr. for exact interpretation of the output, visit thenetinet/tcp.hheader file ๐show thread [addr]โ if noaddris specified, it shows detailed information about the current thread. otherwise, information about the thread ataddris printed โจshow threadsโ shows all threads within the system ๐ the output format goes like this:- First column โ thread identifier (TID)
- Second column โ thread structure address
- Third column โ backtrace.
show tty addrโ drops the contents of a TTY structure, but in a readable form so your eyes don't bleed ๐show turnstile addrโ shows thestruct turnstilestructure living at address addr. Turnstiles are these little structures inside the FreeBSD kernel that implement synchronization primitives which, while holding a specific type of lock, cannot sleep or context switch to another thread. RN the ones in question are:mutex(9),rwlock(9),rmlock(9).show umaโ shows UMA allocator statistics. The output is five columns, bestie, count 'em:Zoneโ name of the UMA zone. Same string that got passed touma_zcreate(9)as the first argument.Sizeโ size of a given memory object (slab).Usedโ number of slabs currently being used.Freeโ number of free slabs within the UMA zone.Requestsโ number of allocation requests to the given zone.
iykyk: the exact same info can be gathered in userspace with a lil help from vmstat -z.
show unpcb addrโ shows the UNIX domain socket private control blockstruct unpcbthat's present at the address addr.show vmochkโ prints whether the internal VM objects are in a map somewhere, and whether none of them have zero ref counts.show vmopagโ this is supposed to show the physical addresses consumed by a VM object. Currently it is not possible to use this command whenwitness(4)is compiled in the kernel ๐ญ so like. keep that in mind.show vnet addrโ prints the virtualized network stackstruct vnetstructure present at the address addr.show vnode [addr]โ prints thestruct vnodestructure lying at [addr]. For the exact interpretation of the output, go look at thesys/vnode.hheader file, no cap.show vnodebufs addrโ shows the clean/dirty buffer lists of the vnode located at addr.show vpath addrโ walks the namecache to look up the pathname of the vnode located at addr.show watchesโ displays all watchpoints. Basically shows the watchpoints you set with the"watch"command ๐show witnessโ shows info about lock acquisition coming from thewitness(4)subsystem.gdbโ toggles between remote GDB and DDB mode. In remote GDB mode you need another machine runninggdb(1)using the remote debug feature, connected to the serial console port on the target machine. Currently only available on the i386 architecture.haltโ halts the system. that's it, that's the whole thing ๐kill sig pidโ sends signal sig to process pid. The signal gets acted on upon returning from the debugger. This one's your girl when you gotta kill a process causing resource contention in the case of a hung system. Seesignal(3)for a list of signals. Note that the arguments are reversed relative tokill(2)โ do not get caught slipping.reboot [seconds]reset [seconds]โ hard reset the system. If the optional argument seconds is given, the debugger will wait for this long โ at most a week โ before rebooting.helpโ prints a short summary of the available commands and command abbreviations. the little cheat sheet, we love her ๐ซถcapture oncapture offcapture resetcapture statusโ ddb supports a basic output capture facility, and it can be used to retrieve the results of debugging commands from userspace usingsysctl(3).capture onenables output capture;capture offdisables it.capture resetclears the capture buffer and disables capture.capture statusreports current buffer use, buffer size, and disposition of output capture.
Userspace processes may inspect and manage ddb capture state using sysctl(8):
debug.ddb.capture.bufsizeโ query or set the current capture buffer size.debug.ddb.capture.maxbufsizeโ query the compile-time limit on the capture buffer size.debug.ddb.capture.bytesโ query the number of bytes of output currently in the capture buffer.debug.ddb.capture.dataโ returns the contents of the buffer as a string to an appropriately privileged process.
This facility is especially useful in concert with the scripting and textdump(4) facilities, letting scripted debugging output get captured and committed to disk as part of a textdump for later analysis. The contents of the capture buffer may also be inspected in a kernel core dump using kgdb(1) โจ
runscriptscriptsunscriptโ run, define, list, and delete scripts. See the"SCRIPTING"section for more on the scripting facility.textdump dumptextdump settextdump statustextdump unsetโ use thetextdump dumpcommand to immediately perform a textdump. More info lives intextdump(4). Thetextdump setcommand may be used to force the next kernel core dump to be a textdump rather than a traditional memory dump or minidump.textdump statusreports whether a textdump has been scheduled.textdump unsetcancels a request to perform a textdump as the next kernel core dump.
โจ VARIABLES โจ
The debugger accesses registers and variables as $name. Register names are as in the "show registers" command. Some variables are suffixed with numbers, and they may have some modifier following a colon immediately after the variable name. For example, register variables can have a u modifier to indicate user register (e.g., "$eax:u").
Built-in variables currently supported are:
radixโ input and output radix.maxoffโ addresses are printed as"symbol+offset"unless offset is greater thanmaxoff.maxwidthโ the width of the displayed line.linesโ the number of lines. It's used by the built-in pager. Setting it to 0 disables paging.tabstopsโ tab stop width.workxxโ work variable; xx can take values from0to31.
๐ EXPRESSIONS ๐
Most expression operators in C are supported โ except '~', '^', and unary '&'. The special rules in ddb are:
- Identifiers โ the name of a symbol is translated to the value of the symbol, which is the address of the corresponding object.
'.'and':'can be used in the identifier. If supported by an object format dependent routine,[filename:]func:lineno,[filename:]variable, and[filename:]linenocan be accepted as a symbol. - Numbers โ radix is determined by the first two letters:
'0x': hex,'0o': octal,'0t': decimal; otherwise, follow the current radix. .โ dot+โ next..โ address of the start of the last line examined. Unlike dot or next, this is only changed by the examine or write command.'โ last address explicitly specified.$variableโ translated to the value of the specified variable. It may be followed by a':'and modifiers as described above.a#bโ a binary operator which rounds up the left hand side to the next multiple of the right hand side.*exprโ indirection. It may be followed by a':'and modifiers as described above.
๐ SCRIPTING ๐
okay bestie, this is the part where ddb gets ambitious. it has a whole little scripting facility so you can automate tasks or set up responses to specific events, no cap. each script is just a list of DDB commands that run one after another in order, and it gets its own unique name. some names are special โ if you define a script with one of those names, it'll run automatically when the matching ddb event happens. iconic behavior honestly.
the script command is how you define a script by name. scripts are a bunch of ddb commands separated with the ; character. like, for example:
script kdb.enter.panic=bt; show pcpu
script lockinfo=show alllocks; show lockedvnods
the scripts command lists all the scripts you've defined so far. ๐
the run command executes a script by name. for example:
run lockinfo
and the unscript command deletes a script by name, rip to that script. for example:
unscript kdb.enter.panic
fun fact: you can also do all of these things from userspace using the ddb(8) command. versatility โจ
๐ฆ the automatic scripts (the ones that run themselves)
certain scripts get run automatically if they're defined, for specific ddb events. here are all the scripts that fire when stuff happens:
kdb.enter.acpiโ the kernel debugger got entered because of anacpi(4)event.kdb.enter.bootflagsโ the kernel debugger got entered at boot because the debugger boot flag was set.kdb.enter.breakโ the kernel debugger got entered because of a serial or console break.kdb.enter.camโ the kernel debugger got entered because of aCAM(4)event.kdb.enter.macโ the kernel debugger got entered because of an assertion failure in themac_test(4)module of the TrustedBSD MAC Framework.kdb.enter.ndisโ the kernel debugger got entered because of anndis(4)breakpoint event.kdb.enter.netgraphโ the kernel debugger got entered because of anetgraph(4)event.kdb.enter.panicโpanic(9)was called.kdb.enter.powerfailโ the kernel debugger got entered because of a powerfail NMI on the sparc64 platform.kdb.enter.powerpcโ the kernel debugger got entered because of an unimplemented interrupt type on the powerpc platform.kdb.enter.sysctlโ the kernel debugger got entered because thedebug.kdb.entersysctl was set.kdb.enter.trapsigโ the kernel debugger got entered because of a trapsig event on the sparc64 platform.kdb.enter.unionfsโ the kernel debugger got entered because of an assertion failure in the union file system.kdb.enter.unknownโ the kernel debugger got entered, but no reason has been set. mysterious. ๐kdb.enter.vfslockโ the kernel debugger got entered because of a VFS lock violation.kdb.enter.watchdogโ the kernel debugger got entered because of a watchdog firing.kdb.enter.witnessโ the kernel debugger got entered because of awitness(4)violation.
and if none of those scripts exist? ddb will try to execute a default script:
kdb.enter.defaultโ the kernel debugger got entered, but no script exactly matching the reason for entering was defined. this is your catch-all for cases you don't specifically care about. for example,kdb.enter.witnesscould be defined to have special handling, andkdb.enter.defaultcould just panic and reboot. the "idk just reboot" strategy, honestly relatable ๐
๐ก HINTS โจ
on machines with an ISA expansion bus, you can literally build a simple NMI generation card by connecting a push button between the A01 and B01 (CHCHK# and GND) card fingers. momentarily shorting those two fingers together may cause the bridge chipset to generate an NMI, which makes the kernel hand control over to ddb. but some bridge chipsets don't generate a NMI on CHCHK#, so your mileage may vary. ๐
the NMI lets you break into the debugger on a wedged machine so you can diagnose problems โ like a little rescue mission. other bus' bridge chipsets may be able to generate NMI using bus specific methods. there are lots of PCI and PCIe add-in cards that can generate NMI for debugging. modern server systems typically use IPMI to generate signals to enter the debugger, and the devel/ipmitool port can send the chassis power diag command, which delivers an NMI to the processor. embedded systems often use JTAG for debugging, but rarely use it in combination with ddb.
for serial consoles, you can enter the debugger by sending a BREAK condition on the serial line โ but only if options BREAK_TO_DEBUGGER is specified in the kernel. most terminal emulation programs can send a break sequence with a special key sequence or via a menu item. however, in some setups sending the break can be difficult to arrange or happens spuriously, so if the kernel contains options ALT_BREAK_TO_DEBUGGER then:
- the sequence of
CR TILDE CTRL-Benters the debugger ๐ซถ CR TILDE CTRL-Pcauses a panic instead of entering the debugger ๐ญCR TILDE CTRL-Rcauses an immediate reboot ๐ฅ
in all the above sequences, CR is a Carriage Return and is usually sent by hitting the Enter or Return key. TILDE is the ASCII tilde character (~). CTRL-x is Control x, created by hitting the control key and then x and then releasing both.
okay so lowkey important: the break-to-enter-the-debugger behavior can be enabled at run-time by setting thesysctl(8)debug.kdb.break_to_debuggerto1. the alternate sequence to enter the debugger behavior can be enabled at run-time by setting thesysctl(8)debug.kdb.alt_break_to_debuggerto1. and the debugger can be entered by setting thesysctl(8)debug.kdb.enterto1. three little sysctls, three big vibes.
๐ FILES
header files mentioned in this manual page can be found below the /usr/include directory:
sys/buf.hsys/domain.hnetinet/in_pcb.hsys/socket.hsys/vnode.h
๐ SEE ALSO
gdb(1), kgdb(1), acpi(4), CAM(4), mac_test(4), ndis(4), netgraph(4), textdump(4), witness(4), ddb(8), sysctl(8), panic(9)
like, go read those too, they're the extended universe bestie ๐
๐ HISTORY
the ddb debugger was developed for Mach, and ported to 386BSD 0.1. this manual page was translated from man(7) macros by Garrett Wollman.
Robert N. M. Watson added support for ddb output capture, textdump(4) and scripting in FreeBSD 7.1. king behavior, honestly ๐
and that's the whole page bestie!! this edition is the Debian one, dated September 7, 2018 โ go forth and debug slayfully, DDB(4) out ๐
โจ
๐ฆ where this page comes from
- debian bookworm: freebsd-manpages 12.2-1 ยท BSD-2-Clause-FreeBSD AND BSD-4-Clause
- debian trixie: freebsd-manpages 12.2-2 ยท BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu jammy: freebsd-manpages 12.2-1 ยท BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu noble: freebsd-manpages 12.2-1 ยท BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu questing: freebsd-manpages 12.2-2
- ubuntu resolute: freebsd-manpages 12.2-2build1 ยท BSD-2-Clause-FreeBSD AND BSD-4-Clause
- ubuntu stonking: freebsd-manpages 12.2-2build1 ยท BSD-2-Clause-FreeBSD AND BSD-4-Clause
- Copyright (c) 1991,1990 Carnegie Mellon University
- Copyright (c) 2007 Robert N. M. Watson
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms