<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset='utf-8'>
<title>System Development & GDB</title>
</head>
<body>
<a href="../index.html">Development Index</a>
<h1>System Development</h1>
<p>System development requires knowing how to debug
kernel know how, in this example will be used Qemu
and GDB. Qemu creates the virtual machine that kernel
will run on and GDB will connect to it to help us
understand how things tick.</p>
<h2>Kernel Build</h2>
<pre>
$ tar xf linux-4.9.48.tar.xz
$ cd linux-4.#!/usr/bin/awk -f
# Constants
BEGIN {
IMAGE_SIZE = 524288 # Amount of simulated RAM
DATA_DEPTH = 8192 # Depth of data stack
ADDRESS_DEPTH = 32768 # Depth of the stacks
# Initialize stacks
data_sp = 0
addr_sp = 0
# VM state
ip = 0
# Opcode definitions
OP_NOP = 0
OP_LIT = 1
OP_DUP = 2
OP_DROP = 3
OP_SWAP = 4
OP_PUSH = 5
OP_POP = 6
OP_JUMP = 7
OP_CALL = 8
OP_CCALL = 9
OP_RETURN = 10
OP_EQ = 11
OP_NEQ = 12
OP_LT = 13
OP_GT = 14
OP_FETCH = 15
OP_STORE = 16
OP_ADD = 17
OP_SUB = 18
OP_MUL = 19
OP_DIVMOD = 20
OP_AND = 21
OP_OR = 22
OP_XOR = 23
OP_SHIFT = 24
OP_ZERO_EXIT = 25
OP_HALT = 26
OP_IE = 27
OP_IQ = 28
OP_II = 29
}
# Stack operations
function stack_push(stack_name, value) {
if (stack_name == "data") {
data_sp++
data_stack[data_sp] = value
} else if (stack_name == "addr") {
addr_sp++
addr_stack[addr_sp] = value
}
}
function stack_pop(stack_name) {
if (stack_name == "data") {
if (data_sp > 0) {
value = data_stack[data_sp]
data_sp--
return value
}
} else if (stack_name == "addr") {
if (addr_sp > 0) {
value = addr_stack[addr_sp]
addr_sp--
return value
}
}
return 0
}
function stack_tos(stack_name) {
if (stack_name == "data" && data_sp > 0) {
return data_stack[data_sp]
}
return 0
}
function stack_nos(stack_name) {
if (stack_name == "data" && data_sp > 1) {
return data_stack[data_sp - 1]
}
return 0
}
# Bitwise operation implementations
function bitwise_and(x, y, i, result, a, b) {
result = 0
for (i = 0; i < 32; i++) {
a = int(x / (2 ^ i)) % 2
b = int(y / (2 ^ i)) % 2
if (a == 1 && b == 1)
result += 2 ^ i
}
return result
}
function bitwise_or(x, y, i, result, a, b) {
result = 0
for (i = 0; i < 32; i++) {
a = int(x / (2 ^ i)) % 2
b = int(y / (2 ^ i)) % 2
if (a == 1 || b == 1)
result += 2 ^ i
}
return result
}
function bitwise_xor(x, y, i, result, a, b) {
result = 0
for (i = 0; i < 32; i++) {
a = int(x / (2 ^ i)) % 2
b = int(y / (2 ^ i)) % 2
if (a != b)
result += 2 ^ i
}
return result
}
function lshift(x, n) {
return int(x * (2 ^ n))
}
function rshift(x, n) {
return int(x / (2 ^ n))
}
# VM instruction implementations
function process_opcode(opcode) {
if (opcode == OP_NOP) {
return
}
else if (opcode == OP_LIT) {
ip++
stack_push("data", image[ip])
}
else if (opcode == OP_DUP) {
stack_push("data", stack_tos("data"))
}
else if (opcode == OP_DROP) {
stack_pop("data")
}
else if (opcode == OP_SWAP) {
temp = stack_pop("data")
temp2 = stack_pop("data")
stack_push("data", temp)
stack_push("data", temp2)
}
else if (opcode == OP_PUSH) {
stack_push("addr", stack_pop("data"))
}
else if (opcode == OP_POP) {
stack_push("data", stack_pop("addr"))
}
else if (opcode == OP_JUMP) {
ip = stack_pop("data") - 1
}
else if (opcode == OP_CALL) {
stack_push("addr", ip)
ip = stack_pop("data") - 1
}
else if (opcode == OP_CCALL) {
a = stack_pop("data")
b = stack_pop("data")
if (b != 0) {
stack_push("addr", ip)
ip = a - 1
}
}
else if (opcode == OP_RETURN) {
ip = stack_pop("addr")
}
else if (opcode == OP_EQ) {
a = stack_pop("data")
b = stack_pop("data")
stack_push("data", (b == a) ? -1 : 0)
}
else if (opcode == OP_NEQ) {
a = stack_pop("data")
b = stack_pop("data")
stack_push("data", (b != a) ? -1 : 0)
}
else if (opcode == OP_LT) {
a = stack_pop("data")
b = stack_pop("data")
stack_push("data", (b < a) ? -1 : 0)
}
else if (opcode == OP_GT) {
a = stack_pop("data")
b = stack_pop("data")
stack_push("data", (b > a) ? -1 : 0)
}
else if (opcode == OP_FETCH) {
x = stack_pop("data")
if (x == -1)
stack_push("data", data_sp)
else if (x == -2)
stack_push("data", addr_sp)
else if (x == -3)
stack_push("data", IMAGE_SIZE)
else if (x == -4)
stack_push("data", -2147483648)
else if (x == -5)
stack_push("data", 2147483647)
else
stack_push("data", image[x])
}
else if (opcode == OP_STORE) {
addr = stack_pop("data")
value = stack_pop("data")
image[addr] = value
}
else if (opcode == OP_ADD) {
x = stack_pop("data")
y = stack_pop("data")
stack_push("data", x + y)
}
else if (opcode == OP_SUB) {
x = stack_pop("data")
y = stack_pop("data")
stack_push("data", y - x)
}
else if (opcode == OP_MUL) {
x = stack_pop("data")
y = stack_pop("data")
stack_push("data", y * x)
}
else if (opcode == OP_DIVMOD) {
b = stack_pop("data")
a = stack_pop("data")
if (b == 0) {
ip = 0
data_sp = 0
addr_sp = 0
} else {
x = abs(b)
y = abs(a)
q = int(y / x)
r = y % x
if (a < 0 && b < 0)
r = r * -1
if (a > 0 && b < 0)
q = q * -1
if (a < 0 && b > 0) {
r = r * -1
q = q * -1
}
stack_push("data", r)
stack_push("data", q)
}
}
else if (opcode == OP_AND) {
x = stack_pop("data")
y = stack_pop("data")
stack_push("data", bitwise_and(x, y))
}
else if (opcode == OP_OR) {
x = stack_pop("data")
y = stack_pop("data")
stack_push("data", bitwise_or(x, y))
}
else if (opcode == OP_XOR) {
x = stack_pop("data")
y = stack_pop("data")
stack_push("data", bitwise_xor(x, y))
}
else if (opcode == OP_SHIFT) {
x = stack_pop("data")
y = stack_pop("data")
if (x < 0)
stack_push("data", lshift(y, -x))
else
stack_push("data", rshift(y, x))
}
else if (opcode == OP_ZERO_EXIT) {
if (stack_tos("data") == 0) {
stack_pop("data")
ip = stack_pop("addr")
}
}
else if (opcode == OP_HALT) {
ip = IMAGE_SIZE
}
check_stack()
}
# Helper functions
function abs(x) {
return x < 0 ? -x : x
}
function check_stack() {
if (data_sp < 0 || addr_sp < 0 ||
data_sp > DATA_DEPTH || addr_sp > ADDRESS_DEPTH) {
ip = 0
data_sp = 0
addr_sp = 0
}
}
function process_packed_opcodes(packed) {
ops[0] = bitwise_and(packed, 255)
ops[1] = bitwise_and(rshift(packed, 8), 255)
ops[2] = bitwise_and(rshift(packed, 16), 255)
ops[3] = bitwise_and(rshift(packed, 24), 255)
for (i = 0; i < 4; i++) {
if (ops[i] != 0) {
process_opcode(ops[i])
}
}
}
# Main execution function
function execute(offset) {
addr_sp = 1
ip = offset
while (ip < IMAGE_SIZE) {
opcode = image[ip]
process_packed_opcodes(opcode)
if (addr_sp == 0)
ip = IMAGE_SIZE
ip++
}
}
# String handling functions
function string_inject(str, buffer, i, len) {
len = length(str)
for (i = 1; i <= len; i++) {
image[buffer + i - 1] = ord(substr(str, i, 1))
image[buffer + i] = 0
}
}
function string_extract(at, str, i) {
str = ""
i = at
while (image[i] != 0) {
str = str chr(image[i])
i++
}
return str
}
# Initialize VM
BEGIN {
prepare_vm()
}
function prepare_vm() {
ip = 0
data_sp = 0
addr_sp = 0
}