Kernel Javascript support


This document details the kernel javascript debugging extension recently added to the reactos kernel.

Enabling

The extension is enabled when KDBG := 1 is set in config in the reactos source tree.

kdb presents the usual prompt when ReactOS starts, but the 'js' command initializes the javascript system and allows the user to start working with the system in javascript.  A welcome banner is displayed when the system is ready, along with the prompt kjs:>.

Using

You may type as many lines in each input as needed.  To cancel some input, just enter '.' as the only character on an input line.  To exit from the javascript interpreter, enter '.' on the first input line.  In order to determine when the user is finished typing, the kernel javascript system uses the harmless ';;' sequence.  Entering ';;' anywhere in the input terminates input and evaluates the current input buffer.  The buffer is emptied afterward.  Any javascript error messages or output are printed before the next prompt is displayed.  Note that the interpreter does not automatically print the evaluation results, so it's useful to wrap simple evaluations with write().

Sample Session

kdb:> js
JS Registry Init Complete. Welcome to ReactOS kernel scripting
Kernel Debugger Script Interface (JavaScript :-)
Terminate input with ;; and end scripting with .
kjs:> write(System.getmodule(1));;
hal.dll,3225501696
kjs:> write(System.getmodule(1)[1].toString(16));;
c0414000
kjs:> write(ebp().toString(16));;
cee8bf84

kjs:> function dump_sec(base) {
..... base2 = peekw(base + 0x3c) + base;
..... sec_off = 0xf8;
..... for( i = 0; peekl(base2 + sec_off + (40 * i)); i++ ) {
..... base_sec = base2 + sec_off + (40 * i);
..... write("Section: " + System.mread(0,base_sec) + "\n");
..... write("RVA: " + peekl(base_sec + 12).toString(16) + "\n");
..... }
..... }
..... ;;
kjs:> dump_sec(0xc0000000);;
Section: .text
RVA: 1000
Section: init
RVA: e6000
Section: .data
RVA: f4000
Section: .edata
RVA: 10d000
Section: .idata
RVA: 115000
Section: .rsrc
RVA: 116000
Section: .bss
RVA: 118000
Section: .reloc
RVA: 15a000

kjs:> var key = "\\registry\\machine\\system\\currentcontrolset\\services\\ne20001\\parameters\\tcpip";;
kjs:> write(regread(key,"defaultgateway"));;
10.0.0.1

Builtin and initialized functions

These functions are available after a successful javascript initialization:

System.getmodule(n) => (string,int) array

Returns the name and base address of the nth module in the kernel module list.

System.mread(s,address) => integer/string

System.mread reads a value from memory and returns it.  s determines what type of read is performed, and address specifies the starting address of the operation.

Valid values of s are:

0 -- Read a null-terminated ascii string
1 -- Read a byte
2 -- Read a word
4 -- Read a dword

System.mwrite(s,address,value) => bool

System.mwrite writes a value to a memory address.  The operand size depends on s, 1 for byte, 2 for word, 4 for dword.

System.print(...) => undefined

Uses DbgPrint to print the specified output.  In javascript, every value is printable, so feel free to give any value type to print.
Use C style escapes for tabs and newlines: \t and \n.

System.regs(int) => int

System.regs read the specified word value from the TRAP_FRAME given to kdb when it was started.  This is useful for locating the stack, along with various other queries.  The machine registers are also provided as named functions by javascript, for example ebp() and eax().

System.regread(key,value) => string/undefined

System.regread reads a string value from the registry (as a member of the specified registry key).  If the read is successful, the string value contained in it is returned.  If the value cannot be read, then undefined is returned.

This method is used by the registry initializer to read the initialization strings.

ebp(), eip(), esp() ... vm86_gs() => int

Every register provided by the system trap frame is available as a global function of the same name.  This makes reading specific registers easy.

peek,peekw,peekl(int addr) => int

Aliases for System.mread([1,2,4],addr)

poke,pokew,pokel(int addr, int value) => int

Aliases for System.mwrite([1,2,4],addr,value)

write(...) => undefined

Alias for System.print