acidtut.ms 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062
  1. .de d0
  2. .nr dP +1
  3. .nr dV +1p
  4. ..
  5. .de d1
  6. .nr dP -1
  7. .nr dV -1p
  8. ..
  9. .nr dT 4
  10. .de Af \" acid function
  11. .CW "\\$1(" "\fI\\$2\fP\f(CW)\fP"
  12. ..
  13. .TL
  14. Native Kernel Debugging with Acid
  15. .AU
  16. Tad Hunt
  17. tad@plan9.bell-labs.com
  18. .br
  19. Lucent Technologies Inc
  20. .br
  21. (Revised 22 May 2000 by Vita Nuova)
  22. .SH
  23. Introduction
  24. .PP
  25. This tutorial provides an introduction to the Acid debugger. It assumes that you are familiar with the features of a typical source-level debugger. The Acid debugger is built round a command language with a syntax similar to C.
  26. This tutorial is not an
  27. introduction to Acid as a whole, but
  28. offers a brief tour
  29. of the basic built in and standard library functions,
  30. especially those needed for debugging native Inferno kernels on a target board.
  31. .PP
  32. Acid was originally developed by Phil Winterbottom
  33. to help debug multi-threaded programs in
  34. the concurrent language Alef, and provide more sophisticated
  35. debugging for C programs.
  36. In the paper
  37. .I "Acid: A Debugger Built From a Language" ,
  38. Winterbottom
  39. discusses Acid's design, including some worked examples of unusual
  40. applications of Acid to find memory leaks and assist code coverage analysis.
  41. Following that is the
  42. .I "Acid Reference Manual" ,
  43. also by Phil Winterbottom,
  44. which gives a more precise specification of the Acid debugging language and its libraries.
  45. .SH
  46. Preliminaries -- the environment
  47. .PP
  48. Acid runs under the host operating system used for cross-development,
  49. in the same way as the Inferno compilers.
  50. Before running either compilers or Acid, the following
  51. environment variables must be set appropriately:
  52. .TS
  53. center;
  54. lf(CW) lf(R)w(4i) .
  55. ROOT T{
  56. the directory in which Inferno lives (eg,
  57. .CW /usr/inferno ).
  58. T}
  59. SYSHOST T{
  60. .I host
  61. operating system type:
  62. .CW Nt ,
  63. .CW Solaris ,
  64. .CW Plan9 ,
  65. .CW Linux
  66. or
  67. .CW FreeBSD
  68. T}
  69. OBJTYPE T{
  70. .I host
  71. machine's architecture type:
  72. .CW 386 ,
  73. .CW sparc ,
  74. .CW mips ,
  75. or
  76. .CW powerpc
  77. T}
  78. .TE
  79. They might be set by a login shell profile
  80. (eg,
  81. Unix
  82. .CW ".profile" ,
  83. or
  84. Plan 9
  85. .CW lib/profile ).
  86. Also ensure that the directory
  87. .P1
  88. $ROOT/$SYSHOST/$OBJTYPE/bin
  89. .P2
  90. is on your search path.
  91. For example, on a Solaris sparc, one might use:
  92. .P1
  93. ROOT=\fIinferno_root\fP
  94. SYSHOST=Solaris
  95. OBJTYPE=sparc
  96. ACIDLIB=$ROOT/lib/acid
  97. PATH=$ROOT/$SYSHOST/$OBJTYPE/bin:$PATH
  98. export ROOT ACIDLIB PATH OBJTYPE SYSHOST
  99. .P2
  100. where
  101. .I "inferno_root"
  102. is the directory in which Inferno lives (eg,
  103. .CW "/usr/inferno" ).
  104. .SH
  105. An Example Program
  106. .PP
  107. The first example is not kernel code, but a small program that
  108. will be compiled but not run, to demonstrate basic Acid commands for
  109. source and object file inspection.
  110. The code is shown below:
  111. .P1
  112. int
  113. factorial(int n)
  114. {
  115. if (n == 1)
  116. return 1;
  117. return n * factorial(n-1);
  118. }
  119. int f;
  120. void
  121. main(void)
  122. {
  123. f = factorial(5);
  124. }
  125. void
  126. _main(void)
  127. {
  128. main();
  129. }
  130. .P2
  131. .SH
  132. Compiling and Linking
  133. .PP
  134. The first step is to create an executable. The example shows the process for creating ARM executables. Substitute the appropriate compiler and linker for other cpu types.
  135. .P1
  136. % 5c factorial.c
  137. % 5l -o factorial factorial.5
  138. % ls
  139. factorial
  140. factorial.5
  141. factorial.c
  142. .P2
  143. .SH
  144. Starting Acid
  145. .PP
  146. Even without the target machine on which
  147. to run the program, many Acid features are available.
  148. The following command starts debugging the
  149. .CW "factorial"
  150. executable. Note that, upon startup, Acid will attempt to load some libaries from the directory specified in the
  151. .CW "ACIDLIB"
  152. environment variable (defaults to
  153. .CW "/usr/inferno/lib/acid" ).
  154. It will also attempt to load the file
  155. .CW "$HOME/lib/acid" ,
  156. in which you can place commands to be executed during startup.
  157. .P1
  158. % acid factorial
  159. factorial:Arm plan 9 executable
  160. $ROOT/lib/acid/port
  161. $ROOT/lib/acid/arm
  162. acid:
  163. .P2
  164. .SH
  165. Exploring the Executable
  166. .PP
  167. To find out what symbols are in the program:
  168. .P1
  169. acid: symbols("")
  170. etext T 0x00001068
  171. f D 0x00002000
  172. setR12 D 0x00002ffc
  173. end B 0x00002008
  174. bdata D 0x00002000
  175. edata D 0x00002008
  176. factorial T 0x00001020
  177. main T 0x00001048
  178. _main T 0x0000105c
  179. acid:
  180. .P2
  181. The output from the
  182. .CW symbols()
  183. function is similar to the output from the
  184. .I nm (10.1)
  185. command. The first column is the symbol name, the second column gives the section the symbol is in, and the third column is the address of the symbol.
  186. .PP
  187. There is also a
  188. .CW "symbols"
  189. global variable. Variables and functions can have the same names. It holds the list of symbol information that the
  190. .CW symbols
  191. function uses to generate the table:
  192. .d0
  193. .P1
  194. acid: symbols
  195. {{"etext", T, 0x00001068}, {"f", D, 0x00002000}, {"setR12", D, 0x00002ffc},
  196. {"end", B, 0x00002008}, {"bdata", D, 0x00002000}, {"edata", D, 0x00002008},
  197. {"factorial", T, 0x00001020}, {"main", T, 0x00001048}, {"_main", T, 0x00001
  198. 05c}}
  199. acid:
  200. .P2
  201. .d1
  202. In large programs, finding the symbol you are interested in from a list that may be thousands of lines long would be difficult. The string argument of
  203. .CW symbols()
  204. is a regular expression against which to match symbols.
  205. All symbols that contain the pattern will be displayed. For example:
  206. .P1
  207. acid: symbols("main")
  208. main T 0x00001048
  209. _main T 0x0000105c
  210. acid: symbols("^main")
  211. main T 0x00001048
  212. acid:
  213. .P2
  214. The
  215. .CW symbols
  216. function is written in the
  217. .I acid
  218. command language and lives in the
  219. .CW "port"
  220. library
  221. .CW $ACIDLIB/port ). (
  222. .P1
  223. defn symbols(pattern)
  224. {
  225. local l, s;
  226. l = symbols;
  227. while l do {
  228. s = head l;
  229. if regexp(pattern, s[0]) then
  230. print(s[0], "\t", s[1], "\t", s[2], "\n");
  231. l = tail l;
  232. }
  233. }
  234. .P2
  235. Acid retrieves the list of symbols from the executable and turns each one into a global variable whose value is the address of the symbol. If the symbol clashes with a builtin name or keyword or a previously defined function, enough
  236. .CW "$"
  237. characters are prepended to the name to make it unique. The list of such renamings is printed at startup.
  238. .PP
  239. Most acid functions operate on addresses. For example, to view the source code for a given address, use the
  240. .CW src
  241. function:
  242. .P1
  243. acid: src(main)
  244. /usr/jrf/factorial.c:10
  245. 5 return n * factorial(n-1);
  246. 6 }
  247. 7
  248. 8 int f;
  249. 9 void
  250. >10 main(void)
  251. 11 {
  252. 12 f = factorial(5);
  253. 13 }
  254. 14
  255. 15 void
  256. .P2
  257. The
  258. .Af "src" addr
  259. function displays a section of source code, with the line containing the address passed as an argument in the middle of the display. To print the assembly code beginning at a given address, use the
  260. .CW asm()
  261. function.
  262. .P1
  263. acid: asm(factorial)
  264. factorial 0x00001020 MOVW.W R14,#-0x8(R13)
  265. factorial+0x4 0x00001024 CMP.S $#0x1,R0
  266. factorial+0x8 0x00001028 MOVW.EQ $#0x1,R0
  267. factorial+0xc 0x0000102c RET.EQ.P #0x8(R13)
  268. factorial+0x10 0x00001030 MOVW R0,n+0(FP)
  269. factorial+0x14 0x00001034 SUB $#0x1,R0,R0
  270. factorial+0x18 0x00001038 BL factorial
  271. factorial+0x1c 0x0000103c MOVW n+0(FP),R2
  272. factorial+0x20 0x00001040 MUL R2,R0,R0
  273. factorial+0x24 0x00001044 RET.P #0x8(R13)
  274. main 0x00001048 MOVW.W R14,#-0x8(R13)
  275. acid:
  276. .P2
  277. The output contains the symbolic address (symbol name+offset, where symbol name is the name of the enclosing function) followed by the absolute address, followed by the disassembled code.
  278. The
  279. .Af "asm" addr
  280. function prints the assembly beginning at
  281. .I "addr"
  282. and ending after either 30 lines have been printed, or the end of the function has been reached. The
  283. .CW "casm()"
  284. function continues the assembly listing from where it left off, even past the end of the function and into the next one.
  285. .P1
  286. acid: casm()
  287. main+0x4 0x0000104c MOVW $#0x5,R0
  288. main+0x8 0x00001050 BL factorial
  289. main+0xc 0x00001054 MOVW R0,$f-SB(SB)
  290. main+0x10 0x00001058 RET.P #0x8(R13)
  291. _main 0x0000105c MOVW.W R14,#-0x4(R13)
  292. acid:
  293. .P2
  294. All the functions presented so far are written in the acid command language. To see the source of a comand written in the acid command language, use the builtin command
  295. .CW "whatis [" "\fIname\fP\f(CW ]\fP."
  296. It prints the definition of the optional argument
  297. .I "name" .
  298. If
  299. .I "name"
  300. is an Acid builtin,
  301. .CW whatis
  302. prints
  303. .CW "builtin function" .
  304. .P1
  305. acid: whatis casm
  306. defn casm() {
  307. asm(lasmaddr);
  308. }
  309. acid:
  310. acid: whatis atof
  311. builtin function
  312. acid:
  313. .P2
  314. If
  315. .I name
  316. is a variable, it prints the type of variable, and for the integer type, gives the format code used to print the value:
  317. .P1
  318. acid: whatis pid
  319. integer variable format D
  320. acid:
  321. .P2
  322. With no arguments,
  323. .CW whatis
  324. lists all available functions:
  325. .P1
  326. acid: whatis
  327. Bsrc bpmask follow new sh
  328. _bpconddel bpneq func newproc source
  329. _bpcondset bpor gpr next spr
  330. _stk bpprint include notestk spsrch
  331. access bppush interpret params src
  332. acidinit bpset itoa pcfile start
  333. addsrcdir bptab kill pcline startstop
  334. asm casm kstk pfl status
  335. atof cont labstk print stk
  336. atoi debug line printto stmnt
  337. bpaddr dump linkreg procs stop
  338. bpand error lkstk rc stopped
  339. bpconddel file locals readfile strace
  340. bpcondset filepc lstk reason symbols
  341. bpdel findsrc map regexp waitstop
  342. bpderef fmt match regs
  343. bpeq fnbound mem setproc
  344. acid:
  345. .P2
  346. The
  347. .Af "Bsrc" addr
  348. function brings up an editor on the line containing
  349. .I "addr" .
  350. It simply invokes a shell script named
  351. .CW "B"
  352. that takes two arguments,
  353. .I "-line"
  354. and
  355. .I "file"
  356. The shell script invokes
  357. .CW "$EDITOR +"
  358. .I "line file" .
  359. If unset,
  360. .CW "EDITOR"
  361. defaults to
  362. .I vi .
  363. The shell script, or the
  364. .CW Bsrc
  365. function can be easily rewritten to work with your favorite editor.
  366. .PP
  367. Entering a symbol name by itself will print the address of the symbol. Prefixing the symbol name with a
  368. .CW "*"
  369. will print the value at the address in the variable. Continuing to use our
  370. .CW "factorial"
  371. example:
  372. .P1
  373. acid: f
  374. 0x00002000
  375. acid: *f
  376. 0x00000000
  377. acid:
  378. .P2
  379. .SH
  380. Remote Debugging
  381. .PP
  382. Now that you have a basic understanding of how to explore the executable, it is time to examine a real remote debugging session.
  383. .PP
  384. We'll use the SA1100 keyboard driver as an example. Examining the kernel configuration file, you'll see the following:
  385. .P1
  386. dev
  387. keyboard
  388. link driver/keyboard port
  389. scanfujn860 kbd.h keycodes.h
  390. link ./../driver plat
  391. kbdfujitsu ./../common/ssp.h \e
  392. /driver/keyboard/kbd.h \e
  393. /driver/keyboard/keycodes.h
  394. port
  395. const char *defaultkeyboard = "fujitsu";
  396. const char *defaultkeytable = "scanfujn860";
  397. int debugkeys = 1; /* 1 = enabled, 0 = disabled */
  398. .P2
  399. This describes the pieces of the keyboard driver which are linked into the kernel. The source code lives in two places,
  400. .CW "$ROOT/os/driver/keyboard" ,
  401. and
  402. .CW "$ROOT/os/plat/sa1100/driver" .
  403. .PP
  404. The next step is to build a kernel. Use the
  405. .I mk
  406. target
  407. .CW acid
  408. to ensure that the Acid symbolic debugging data is
  409. produced.
  410. For example:
  411. .P1
  412. % mk 'CONF=sword' acid isword.p9.gz
  413. .P2
  414. This creates the Acid file
  415. .CW isword.acid ,
  416. containing Acid declarations describing kernel structures,
  417. the kernel executable
  418. .CW isword.p9 ;
  419. and finally
  420. .I gzip s
  421. a copy of the kernel in
  422. .CW isword.p9.gz
  423. to load onto the device. Next, copy the gzipped image onto the device and then boot it. Follow the directions found elsewhere for details of this process.
  424. .PP
  425. From a shell prompt on the target device, start the remote debugger by writing the letter
  426. .CW r
  427. (for run) to
  428. .CW "#b/dbgctl" .
  429. Next, start Acid in remote debug mode, specifying the serial port it is connected to with the
  430. .CW "-R"
  431. option.
  432. .CW "$CONF"
  433. is the name of the configuration file used, for example
  434. .CW "sword" .
  435. .P1
  436. % acid -R /dev/cua/b -l i$CONF.acid i$CONF
  437. isword:Arm plan 9 executable
  438. $ROOT/lib/acid/port
  439. i$CONF.acid
  440. $ROOT/lib/acid/arm
  441. /usr/jrf/lib/acid
  442. acid:
  443. .P2
  444. You are now debugging the kernel that is running on the target device. All of the previously listed commands will work as described before, in addition, there are many more commands available.
  445. .SH
  446. Kernel Process Listing
  447. .PP
  448. To get a list of kernel processes, use the
  449. .CW "ps()"
  450. function:
  451. .P1
  452. acid: ps()
  453. PID PC PRI STATE NAME
  454. 1 0x00054684 5 Queueing interp
  455. 2 0x00000000 1 Wakeme consdbg
  456. 3 0x00000000 5 Wakeme tcpack
  457. 4 0x00000000 5 Wakeme Fs.sync
  458. 5 0x00000000 4 Wakeme touchscreen
  459. 6 0x00054684 5 Queueing dis
  460. 7 0x00059788 5 Wakeme dis
  461. 8 0x00054684 5 Queueing dis
  462. 9 0x00054684 5 Queueing dis
  463. 10 0x00054684 5 Wakeme dis
  464. 11 0x0004c26c 1 Running dbg
  465. acid:
  466. .P2
  467. The
  468. .CW "PC"
  469. column shows the address the process was executing at when the
  470. .CW ps
  471. command retrieved statistics on it. The
  472. .CW "PRI"
  473. column lists process priorities. The smaller the number the higher the process priority. Notice that the kernel process (kproc) running the debugger is the highest priority process in the system. The only process you will ever see in the
  474. .CW "Running"
  475. state while executing the
  476. .CW ps
  477. command will be the debugger, since it is gathering information about the other processes.
  478. .SH
  479. Breakpoints
  480. .PP
  481. Breakpoints in Inferno, unlike most traditional kernel debuggers, are conditional breakpoints. There are minimally two conditions which must be met. These conditions are address and process id. A breakpoint will only be taken when execution for a specific kernel process reaches the specified address. The user can create additional conditions that are evaluated if the address and process id match. If evaluation of these conditions result in a nonzero value, the breakpoint is taken, otherwise it is ignored, and execution continues.
  482. .PP
  483. Again, the best way to proceed is with an example:
  484. .P1
  485. acid: setproc(7)
  486. .P2
  487. The
  488. .Af setproc pid
  489. function selects a kproc to which later commands will be applied;
  490. the one with process ID (\fIpid\fP)
  491. in this case.
  492. .P1
  493. acid: bpset(keyboardread)
  494. Waiting...
  495. 7: stopped flush8to4+0x18c MOVW (R3<<#4),R3
  496. .P2
  497. After selecting a kproc, we set a breakpoint at the address referred to by the
  498. .CW "keyboardread"
  499. symbol. As described before, the value of a global variable created from a symbol in the executable is the address of the symbol. In this case the address is the first instruction in the
  500. .CW "keyboardread()"
  501. function. Notice that setting a breakpoint stops the kproc from executing. A bit later, we'll see how to get it to continue execution.
  502. .PP
  503. Next, display the list of breakpoints using
  504. .CW "bptab()" :
  505. .P1
  506. acid: bptab()
  507. ID PID ADDR CONDITIONS
  508. 0 7 keyboardread 0x0003c804 { }
  509. .P2
  510. The first column is a unique number that identifies the breakpoint. The second column is the process ID in which the breakpoint will be taken. The third and fourth columns are the address of the breakpoint, first in symbolic form, then in numeric form. Finally, the last column is a list of conditions to evaluate whenever the kproc specified in the
  511. .CW "PID"
  512. column hits the the address specified in the
  513. .CW "ADDR"
  514. column. When they match, the list of conditions is evaluated. If the result is nonzero, the breakpoint is taken. Since we used the simplified breakpoint creation function,
  515. .CW "bpset()"
  516. , there are no additional conditions. Later on, we'll see how to set conditional breakpoints.
  517. .PP
  518. Start the selected kproc executing again, and wait for it to hit the breakpoint.
  519. .P1
  520. acid: cont()
  521. .P2
  522. The
  523. .CW "cont()"
  524. function will not return until a breakpoint has been hit, and there is no way to interrupt it. This means you should only set breakpoints that will be hit, otherwise you'll have to reboot the target device and restart your debugging session.
  525. .PP
  526. To continue our example, repeatedly hit new line (return, enter)
  527. on the keyboard on the target device, until the breakpoint occurs:
  528. .P1
  529. break 0: pid 7: stopped keyboardread SUB $#0xa4,R13,R13
  530. acid:
  531. .P2
  532. This message, followed by the interactive prompt returning tells you that a breakpoint was hit. It gives the breakpoint id, the kernel process id, then the symbolic address at which execution halted, followed by the disassembly of the instruction at that address.
  533. .PP
  534. The
  535. .CW "kstk()"
  536. function prints a kernel stack trace, beginning with the current frame, all the way back to the call that started the kproc. For each function, it gives the name name, arguments, source file, and line number, followed by the symbolic address, source file, and line number of the caller.
  537. .d0
  538. .P1
  539. acid: kstk()
  540. At pc:247812:keyboardread /usr/inferno/os/driver/keyboard/devkey
  541. board.c:350
  542. keyboardread(offset=0x0000009d,buf=0x001267f8,n=0x00000001) /usr
  543. /inferno/os/driver/keyboard/devkeyboard.c:350
  544. called from kchanio+0x9c /usr/inferno/os/port/sysfile.c:
  545. 75
  546. kchanio(buf=0x001267f8,n=0x00000001,mode=0x00000000) /usr/infern
  547. o/os/port/sysfile.c:64
  548. called from consread+0x144 /usr/inferno/os/driver/port/d
  549. evcons
  550. consread(offset=0x0000009d,buf=0x0043d4fc,n=0x00000400,c=0x0044e
  551. c38) /
  552. usr/inferno/os/driver/port/devcons.c:357
  553. called from kread+0x164 /usr/inferno/os/port/sysfile.c:2
  554. 97
  555. kread(fd=0x00000006,n=0x00000400,va=0x0043d4fc) /usr/inferno/os/
  556. port/sysfile.c:272
  557. called from Sys_read+0x84 /usr/inferno/os/port/inferno.c
  558. :244
  559. Sys_read() /usr/inferno/os/port/inferno.c:229
  560. called from mcall+0x98 /usr/inferno/interp/xec.c:590
  561. mcall() /usr/inferno/interp/xec.c:569
  562. called from xec+0x128 /usr/inferno/interp/xec.c:1098
  563. xec(p=0x0044edd8) /usr/inferno/interp/xec.c:1077
  564. called from vmachine+0xbc /usr/inferno/os/port/dis.c:706
  565. vmachine() /usr/inferno/os/port/dis.c:677
  566. called from _main+0x50 /usr/inferno/os/plat/sa1100/infern
  567. o/main.c:237
  568. acid:
  569. .P2
  570. .d1
  571. There is another kernel stack dump function,
  572. .CW "lkstk()"
  573. which shows the same information as
  574. .CW "kstk()"
  575. plus the names and values of local variables. Notice that in addition to the
  576. `called from'
  577. information, each local variable and its value is listed on a line by itself.
  578. .d0
  579. .P1
  580. acid: lkstk()
  581. At pc:247812:keyboardread /usr/inferno/os/driver/keyboard/devkeyboard.
  582. c:350
  583. keyboardread(offset=0x00000018,buf=0x001267f9,n=0x00000001) /usr/inferno
  584. /os/driver/keyboard/devkeyboard.c:350
  585. called from kchanio+0x9c /usr/inferno/os/port/sysfile.c:75
  586. tmp=0x00000000
  587. kchanio(buf=0x001267f9,n=0x00000001,mode=0x00000000) /usr/inferno/os/por
  588. t/sysfile.c:64
  589. called from consread+0x144 /usr/inferno/os/driver/port/devcons
  590. c=0x0045a858
  591. r=0x00000001
  592. consread(offset=0x00000015,buf=0x0043d4fc,n=0x00000400,c=0x0044ec38) /us
  593. r/inferno/os/driver/port/devcons.c:357
  594. called from kread+0x164 /usr/inferno/os/port/sysfile.c:297
  595. r=0x00000001
  596. ch=0x0000006c
  597. eol=0x00000000
  598. i=0x00000000
  599. mt=0x60000053
  600. tmp=0x0007317c
  601. l=0x0044ec38
  602. p=0x00049754
  603. kread(fd=0x00000006,n=0x00000400,va=0x0043d4fc) /usr/inferno/os/port/sys
  604. file.c:272
  605. called from Sys_read+0x84 /usr/inferno/os/port/inferno.c:244
  606. c=0x0044ec38
  607. dir=0x00000000
  608. Sys_read() /usr/inferno/os/port/inferno.c:229
  609. called from mcall+0x98 /usr/inferno/interp/xec.c:590
  610. f=0x0044eff0
  611. n=0x00000400
  612. mcall() /usr/inferno/interp/xec.c:569
  613. called from xec+0x128 /usr/inferno/interp/xec.c:1098
  614. ml=0x0043d92c
  615. f=0x0044eff0
  616. xec(p=0x0044edd8) /usr/inferno/interp/xec.c:1077
  617. called from vmachine+0xbc /usr/inferno/os/port/dis.c:706
  618. vmachine() /usr/inferno/os/port/dis.c:677
  619. called from _main+0x50 /usr/inferno/os/plat/sa1100/inferno/main.
  620. c:237
  621. r=0x0044edd8
  622. o=0x0044ee50
  623. .P2
  624. .d1
  625. The
  626. .CW "step()"
  627. function allows the currently selected process to execute a single instruction, and then stop.
  628. .P1
  629. acid: step()
  630. break 1: pid 7: stopped keyboardread+0x4 MOVW R14,#0x0(R13)
  631. acid:
  632. .P2
  633. The
  634. .CW "bpdel" (
  635. .I id )
  636. command deletes the breakpoint identified by
  637. .I id :
  638. .P1
  639. acid: bpdel(0)
  640. .P2
  641. The
  642. .CW "start()"
  643. command places the kproc back into the state it was in when it was stopped.
  644. .P1
  645. acid: start(7)
  646. acid:
  647. .P2
  648. Now lets look at how to set conditional breakpoints.
  649. .d0
  650. .P1
  651. acid: bpcondset(7, keyboardread, {bppush(_startup), bpderef()})
  652. Waiting...
  653. 7: stopped sched+0x20 MOVW #0xffffff70(R12),R6
  654. acid: bptab()
  655. ID PID ADDR CONDITIONS
  656. 0 7 keyboardread 0x0003c804 {
  657. {"p", 0x00008020}
  658. {"*", 0x00000000} }
  659. acid: *_startup = 0
  660. acid: cont()
  661. .P2
  662. .d1
  663. Conditional breakpoints are set with
  664. .CW "bpcondset()"
  665. . It takes three arguments, the kernel process id, the address, and a list of stack based operations which are executed if the pid and addr match. The operations push values onto the stack, and if at the end of execution, a nonzero value is on the top of the stack, the breakpoint is taken. Examining the list of breakpoints with the
  666. .CW "bptab()"
  667. function shows the list of conditions to apply. The list is a bit confusing to read, but the
  668. .CW ""p""
  669. means push and the
  670. .CW ""*""
  671. means
  672. .I dereference .
  673. .PP
  674. No matter how much you type on the keyboard, this particular breakpoint will never be taken. That's because before continuing, we set the value at the address
  675. .CW "_startup"
  676. to zero, so whenever execution reaches
  677. .CW "keyboardread"
  678. in kproc number 7, it pushes the address
  679. .CW "_startup" ,
  680. then pops it and pushes the word at that address. Since the top of the stack is zero, the breakpoint is ignored.
  681. .PP
  682. This contrived example may not be all that useful, but you can use a similar method in your driver to examine some state before making the decision to take the breakpoint.
  683. .SH
  684. Examining Registers
  685. .PP
  686. There are three commands to dump registers:
  687. .CW gpr() ,
  688. .CW spr()
  689. and
  690. .CW "regs()" .
  691. The
  692. .CW "gpr()"
  693. function dumps the general purpose registers,
  694. .CW "spr()"
  695. dumps special purpose registers (such as the
  696. .CW "PC"
  697. and
  698. .CW "LINK "
  699. registers), and
  700. .CW "regs()"
  701. dumps both:
  702. .d0
  703. .P1
  704. acid: regs()
  705. PC 0x0004a3b0 sched+0x20 /home/tad/inf2.1/os/port/proc.c:82
  706. LINK 0x0004b8e8 kchanio+0xa4 /home/tad/inf2.1/os/port/sysfile.c:75
  707. SP 0x00453c4c
  708. R0 0x00458798 R1 0x000fdf9c R2 0x0003c804 R3 0x00000000
  709. R4 0xffffffff R5 0x00000001 R6 0x00458798 R7 0x00000001
  710. R8 0x001267f8 R9 0x00000000 R10 0x0044ee50 R11 0x00029f9c
  711. R12 0x000fc854
  712. acid:
  713. .P2
  714. .d1
  715. .SH
  716. Complex Types
  717. .PP
  718. When reading in the symbol table, Acid treats all of the symbols in the executable as pointers to integers. This is fine for global integer variables, but it makes examining more complex types difficult. Luckily there is a solution. Acid allows you to create a description for more complex types, and a function which will automatically be called for these complex types. In fact, the compiler can automatically generate the acid code to describe these complex types. For example, if we wanted to print out the devtab structure for the keyboard driver, we can just give its name:
  719. .P1
  720. acid: whatis keyboarddevtab
  721. integer variable format a complex Dev
  722. acid: keyboarddevtab
  723. dc 107
  724. name 0x0010e0ea
  725. reset 0x0003c3fc
  726. init 0x0003c438
  727. attach 0x0003c5dc
  728. clone 0x000480d0
  729. walk 0x0003c600
  730. stat 0x0003c640
  731. open 0x0003c680
  732. create 0x0004881c
  733. close 0x0003c768
  734. read 0x0003c804
  735. bread 0x0004883c
  736. write 0x0003c968
  737. bwrite 0x00048900
  738. remove 0x00048978
  739. wstat 0x00048998
  740. acid:
  741. .P2
  742. Acid knows the keyboarddevtab variable is of type Dev, and it prints it by invoking the function Dev(keyboarddevtab).
  743. .P1
  744. acid: whatis Dev
  745. complex Dev {
  746. 'D' 0 dc;
  747. 'X' 4 name;
  748. 'X' 8 reset;
  749. 'X' 12 init;
  750. 'X' 16 attach;
  751. 'X' 20 clone;
  752. 'X' 24 walk;
  753. 'X' 28 stat;
  754. 'X' 32 open;
  755. 'X' 36 create;
  756. 'X' 40 close;
  757. 'X' 44 read;
  758. 'X' 48 bread;
  759. 'X' 52 write;
  760. 'X' 56 bwrite;
  761. 'X' 60 remove;
  762. 'X' 64 wstat;
  763. };
  764. .P3
  765. defn Dev(addr) {
  766. complex Dev addr;
  767. print("\etdct",addr.dc,"\en");
  768. print("\etnamet",addr.nameX,"\en");
  769. print("\etresett",addr.resetX,"\en");
  770. print("\etinitt",addr.initX,"\en");
  771. print("\etattacht",addr.attachX,"\en");
  772. print("\etclonet",addr.cloneX,"\en");
  773. print("\etwalkt",addr.walkX,"\en");
  774. print("\etstatt",addr.statX,"\en");
  775. print("\etopent",addr.openX,"\en");
  776. print("\etcreatet",addr.createX,"\en");
  777. print("\etcloset",addr.closeX,"\en");
  778. print("\etreadt",addr.readX,"\en");
  779. print("\etbreadt",addr.breadX,"\en");
  780. print("\etwritet",addr.writeX,"\en");
  781. print("\etbwritet",addr.bwriteX,"\en");
  782. print("\etremovet",addr.removeX,"\en");
  783. print("\etwstatt",addr.wstatX,"\en");
  784. }
  785. .P2
  786. Notice the complex type definition and the function to print the type both have the same name. If we know that an address is the address of a complex type, even though acid may not
  787. (say we're storing multiple types of data in a void pointer),
  788. we can print the complex type by calling the type printing function ourselves.
  789. .P1
  790. acid: print(fmt(keyboarddevtab, 'X'))
  791. 0x00106d50
  792. acid: Dev(0x00106d50)
  793. dc 107
  794. name 0x0010e0ea
  795. reset 0x0003c3fc
  796. init 0x0003c438
  797. attach 0x0003c5dc
  798. clone 0x000480d0
  799. walk 0x0003c600
  800. stat 0x0003c640
  801. open 0x0003c680
  802. create 0x0004881c
  803. close 0x0003c768
  804. read 0x0003c804
  805. bread 0x0004883c
  806. write 0x0003c968
  807. bwrite 0x00048900
  808. remove 0x00048978
  809. wstat 0x00048998
  810. acid:
  811. .P2
  812. .SH
  813. Conclusion
  814. .PP
  815. This introduction to using Acid for remote debugging Inferno kernels should be enough to get you started. As a tutorial, it only describes how to use some of the features of the debugger, and does not attempt to describe how to do advanced debugging such as writing your own functions, or modifying existing ones. Exploring the source, setting breakpoints, single stepping through code, and examining the contents of variables are the usual uses of a debugger. This tutorial gives examples of all of these.
  816. .PP
  817. For a more in depth discussion of the acid command language, and how to write your own acid functions, see the manual page
  818. .I acid (10.1)
  819. and Phil Winterbottom's papers on the Acid Debugger,
  820. reprinted in this volume.
  821. .TL
  822. Appendix
  823. .LP
  824. There are two important differences between Acid described in the
  825. accompanying paper, and Acid as distributed with Inferno for use in
  826. kernel debugging.
  827. .SH
  828. Connecting Acid to the remote Inferno kernel
  829. .PP
  830. A remote Plan 9 kernel can be debugged in the same
  831. way as a Plan 9 user process, using the
  832. file server
  833. .I rdbfs (4).
  834. It is a user-level file server on Plan 9 that
  835. uses a special debugging protocol on a serial connection to
  836. the remote kernel, but on the Plan 9 side serves a file system interface
  837. like that of
  838. .I proc (3),
  839. for use by Acid.
  840. Acid therefore does not need any special code to access the remote kernel's memory,
  841. or exert control over it.
  842. .PP
  843. Inferno's version of Acid currently runs under the host operating systems,
  844. which do not support such a mechanism (except for Plan 9).
  845. Instead, Acid itself provides a special debugging protocol,
  846. with (host) platform-specific interface code to access a serial port.
  847. This might well be addressed in future by implementing the native kernel debugger
  848. in Limbo.
  849. .SH
  850. Handling of breakpoints
  851. .PP
  852. .de Ip
  853. .KS
  854. .LP
  855. .tl '\f2\\$1\fP\ \ \f(CW\\$2(\f2\\$3\f(CW)\f1''\\$4'
  856. .IP
  857. ..
  858. .de Ex
  859. .KE
  860. .KS
  861. .IP
  862. .ft CW
  863. .ta 4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n +4n
  864. .nf
  865. .in +4n
  866. .br
  867. ..
  868. .de Ee
  869. .fi
  870. .ft 1
  871. .br
  872. .in -4n
  873. .KE
  874. ..
  875. The following functions are provided by the Acid library
  876. .CW $ROOT/lib/acid/$OBJTYPE
  877. for use in native kernel debugging.
  878. In several cases they change the behavior described in the Acid manual.
  879. The functions are:
  880. .P1
  881. id = bpset(addr)
  882. id = bpcondset(pid, addr, list)
  883. bppush(val)
  884. bpderef()
  885. bpmask()
  886. bpeq()
  887. bpneq()
  888. bpand()
  889. bpor()
  890. bptab()
  891. addr = bpaddr(id)
  892. bpdel(id)
  893. bpconddel(id)
  894. .P2
  895. .PP
  896. With traditional breakpoints, when a program reaches an address at which a breakpoint is set, execution is halted, and the debugger is notified. In applications programming, this type of breakpoint is sufficient because communicating the break in execution to the debugger is handled by the operating system. The traditional method of handling breakpoints breaks down when program being debugged is the kernel. A breakpoint cannot entirely suspend the execution of the kernel because there is no other program that can handle the communication to the debugger.
  897. .PP
  898. Some operating systems solve this problem by including a
  899. `mini' operating system,
  900. a self-contained program within the kernel that has its own code to handle the hardware used to communicate with the remote debugger or user. There are many problems with this mechanism. First, the debugger code that lives inside the kernel must duplicate a lot of code contained elsewhere in the kernel. This makes the kernel much bigger, and can increase maintenance costs. Typically this type of debug support treats the kernel as having a single thread of control, so a breakpoint stops everything while the user decides what to do about it. The only places in the kernel breakpoints cannot be set are in the debugger itself, and in the code that handles notifying the debugger of the breakpoint.
  901. .PP
  902. The Inferno kernel takes a different approach. The remote debug support is provided by a device driver that makes use of kernel services. Communication with the remote debugger is handled by a kernel process dedicated entirely to that task. All breakpoints can be considered to be minimally conditional on two values. First, the address to take the break at, and second, the kernel process to take the break in. This method allows the kernel debugger to be implemented as a regular Inferno device driver. The device driver can make use of all the APIs available to device drivers, it does not need to be self contained. Additionally, conditional breakpoints can be set anywhere in the kernel, with two exceptions. As with traditional debugger implementations, breakpoints can not be set in the code that handles notifying the debugger of the breakpoint. Unlike traditional implementations, the code that handles the execution and evaluation of the conditions applied to the breakpoint is the only other place breakpoint
  903. cannot be set. Since both of these parts of the kernel code are self contained, the user can set breakpoints in any other kernel routines. For example, the user could set a breakpoint in
  904. .CW kread() ,
  905. for a given kernel process, but the debugger can still call
  906. .CW kread()
  907. itself.
  908. .PP
  909. Use of conditional breakpoints can help make the debugging process more efficient. If there is a bug that occurs in the Nth iteration of a loop, with unconditional breakpoints, user intervention is required N-1 times before reaching the state the bug occurs in. Conditional breakpoints give the user the ability to automatically check the value of N, and only take the breakpoint when it reaches the critical value.
  910. .PP
  911. The following changed
  912. and additional functions in the Acid library provide access
  913. to this extended breakpoint support:
  914. .SH
  915. Setting Breakpoints
  916. .LP
  917. .\"
  918. .\"
  919. .\"
  920. .Ip integer bpset integer "Set a breakpoint
  921. .CW bpset
  922. places an unconditional breakpoint for the currently
  923. selected kernel process at the address specified
  924. by its
  925. .I integer
  926. argument.
  927. It returns the ID of the newly created breakpoint, or the nil list on error.
  928. It is simply shorthand for a call
  929. .Ex
  930. bpcondset(pid, addr, {})
  931. .Ee
  932. where
  933. .I pid
  934. is the global variable identifying the currently selected process,
  935. .I addr
  936. is the user-supplied address for the breakpoint,
  937. and
  938. .CW {}
  939. is the empty list, signifying no conditions.
  940. .Ip integer bpcondset "pid,addr,list" "Set conditional breakpoint
  941. Sets a conditional breakpoint at addr for the kernel process identified by
  942. .I pid .
  943. The
  944. .I list
  945. argument is a list of operations that are executed when execution reaches
  946. .I addr .
  947. If execution results in a a non-zero value on the top of the stack, the breakpoint is taken, otherwise it is skipped.
  948. The
  949. .I list
  950. is in reverse polish notation format, and has these operations:
  951. .Ex
  952. PUSH
  953. DEREF (pop val, push *(ulong*)val)
  954. MASK (pop mask, pop value, push value & mask)
  955. EQ (pop v1, pop v2, push v1 == v2)
  956. NEQ (pop v1, pop v2, push v1 != v2)
  957. AND (pop v1, pop v2, push v1 && v1)
  958. OR (pop v1, pop v2, push v1 || v2)
  959. .Ee
  960. Condition lists are executed in a single pass, starting with the first command in the list, ending with the last. If a nonzero value is on the top of the stack at the end of execution, the breakpoint is taken, otherwise it is skipped.
  961. .RS
  962. .LP
  963. In effect, there are two mandatory conditions, the address of the breakpoint, and the kernel process id. These two conditions must be met for the condition list to be processed. If these conditions are met, the entire condition list is processed, there is no short circuit evaluation path.
  964. .LP
  965. For example, given the following code fragment:
  966. .P1 +.4i
  967. int i;
  968. for(i=0; i<1000; i++) {
  969. ...
  970. }
  971. .P2
  972. the following call to
  973. .CW bpcondset()
  974. sets a conditional breakpoint to be taken when execution reaches
  975. .I addr
  976. in kernel process
  977. .I pid
  978. on the 500th iteration of the loop:
  979. .P1 +.4i
  980. bpcondset(pid, addr, {bppush(i),
  981. bpderef(), bppush(500), bpeq()});
  982. .P2
  983. .RE
  984. .SH
  985. Condition List Construction
  986. .LP
  987. .Ip list bppush val "Construct breakpoint stack
  988. Push val onto the stack.
  989. .KE
  990. .Ip list bpderef "" "Construct breakpoint stack
  991. Replace the value at the top of the stack with the value found at the address obtained by treating value at the top of the stack as an address. Pop the value on the top of the stack, treat it as a ulong*, and push the value at the address.
  992. .Ex
  993. addr = pop();
  994. push(*(ulong*)addr);
  995. .Ee
  996. .Ip list bpmask "" "Construct breakpoint stack
  997. Replace the top two values on the stack with the value obtained by masking the second value on the stack with the top of the stack.
  998. .Ex
  999. mask = pop();
  1000. value = pop();
  1001. push(value & mask);
  1002. .Ee
  1003. .Ip list bpeq "" "Construct breakpoint stack
  1004. Comparison of the top two values on the stack. Replace the top two values on the stack with a 1 if the values are equal, or a zero if they are not.
  1005. .Ex
  1006. v1 = pop();
  1007. v2 = pop();
  1008. push(v1 == v2);
  1009. .Ee
  1010. .Ip list bpneq "" "Construct breakpoint stack
  1011. Negative comparison of the top two values on the stack. Replace the top two values on the stack with a 0 if the values are equal, or 1 if they are not.
  1012. .Ex
  1013. v1 = pop();
  1014. v2 = pop();
  1015. push(v1 != v2);
  1016. .Ee
  1017. .Ip list bpand "" "Construct breakpoint stack
  1018. Logical and of the top two values on the stack. Replace the top two values on the stack with a 0 if both are zero, or 1 if both are nonzero.
  1019. .Ex
  1020. v1 = pop();
  1021. v2 = pop();
  1022. push(v1 && v2);
  1023. .Ee
  1024. .Ip list bpor "" "Construct breakpoint stack
  1025. Logical or of the top two values on the stack. Replace the top two values on the stack with a 1 if either is nonzero, 0 otherwise.
  1026. .Ex
  1027. v1 = pop();
  1028. v2 = pop();
  1029. push(v1 || v2);
  1030. .Ee
  1031. .SH
  1032. Breakpoint Status
  1033. .LP
  1034. .Ip {} bptab "" "List active breakpoints
  1035. Prints the list of breakpoints containing the following information in order: breakpoint number, kernel process id, breakpoint address, and the list of conditions to execute to determine if the breakpoint will be taken.
  1036. .Ex
  1037. acid: bptab()
  1038. ID PID ADDR CONDITIONS
  1039. 0 1 consread+0x20 0x216cc {}
  1040. acid:
  1041. .Ee
  1042. .Ip integer bpaddr id "Address of breakpoint
  1043. Returns the address the breakpoint identified by
  1044. .I id
  1045. is set to trigger on.
  1046. .KE
  1047. .SH
  1048. Deleting breakpoints
  1049. .Ip {} bpdel id "Delete breakpoint
  1050. Delete the breakpoint identified by
  1051. .I id .
  1052. Shorthand for bpconddel().
  1053. .KE
  1054. .Ip {} bpconddel id "Delete conditional breakpoint
  1055. Delete the conditional breakpoint identified by the integer
  1056. .I id .
  1057. .KE