Move images next to their corresponding posts
@@ -241,7 +241,7 @@ It is important that the function is [diverging], i.e. it must never return. The
|
||||
|
||||
[diverging]: https://doc.rust-lang.org/book/functions.html#diverging-functions
|
||||
|
||||

|
||||

|
||||
|
||||
If our handler function returned normally, it would try to pop the return address from the stack. But it might get some completely different value then. For example, the CPU pushes an error code for some exceptions. Bad things would happen if we interpreted this error code as return address and jumped to it. Therefore interrupt handler functions must diverge[^fn-must-diverge].
|
||||
|
||||
@@ -550,7 +550,7 @@ pub extern "C" fn rust_main(...) {
|
||||
|
||||
It works! We see a `EXCEPTION: DIVIDE BY ZERO` message at the bottom of our screen:
|
||||
|
||||

|
||||

|
||||
|
||||
## What's next?
|
||||
We've successfully caught our first exception! However, our `EXCEPTION: DIVIDE BY ZERO` message doesn't contain much information about the cause of the exception. The next post improves the situation by printing i.a. the current stack pointer and address of the causing instruction. We will also explore other exceptions such as page faults, for which the CPU pushes an _error code_ on the stack.
|
||||
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -24,7 +24,7 @@ An exception signals that something is wrong with the currently-executed instruc
|
||||
|
||||
This routine involves reading the interrupt descriptor table and invoking the registered handler function. But first, the CPU pushes various information onto the stack, which describe the current state and provide information about the cause of the exception:
|
||||
|
||||

|
||||

|
||||
|
||||
The pushed information contain the instruction and stack pointer, the current CPU flags, and (for some exceptions) an error code, which contains further information about the cause of the exception. Let's look at the fields in detail:
|
||||
|
||||
@@ -86,7 +86,7 @@ So the inline assembly loads the stack pointer value to `stack_frame` at the ver
|
||||
### Testing it
|
||||
Let's try it by executing `make run`:
|
||||
|
||||

|
||||

|
||||
|
||||
Those `ExceptionStackFrame` values look very wrong. The instruction pointer definitely shouldn't be 1 and the code segment should be `0x8` instead of some big number. So what's going on here?
|
||||
|
||||
@@ -255,7 +255,7 @@ lazy_static! {
|
||||
|
||||
Now we see a correct exception stack frame when we execute `make run`:
|
||||
|
||||

|
||||

|
||||
|
||||
## Testing on real Hardware
|
||||
Virtual machines such as QEMU are very convenient to quickly test our kernel. However, they might behave a bit different than real hardware in some situations. So we should test our kernel on real hardware, too.
|
||||
@@ -602,7 +602,7 @@ pub extern "C" fn rust_main(multiboot_information_address: usize) {
|
||||
|
||||
We get the following output:
|
||||
|
||||

|
||||

|
||||
|
||||
### The Page Fault Error Code
|
||||
“Error code 2” is not really an useful error message. Let's improve this by creating a `PageFaultErrorCode` type:
|
||||
@@ -647,7 +647,7 @@ The `from_bits` function tries to convert the `u64` into a `PageFaultErrorCode`.
|
||||
|
||||
Now we get a useful error message when a page fault occurs, which allows us to debug it more easily:
|
||||
|
||||

|
||||

|
||||
|
||||
As expected, the page fault was caused by write to `0xdeadbeaf`. The `PROTECTION_VIOLATION` flag is not set, so the accessed page was not present.
|
||||
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
@@ -101,20 +101,20 @@ pub extern "C" fn rust_main(...) {
|
||||
|
||||
When we execute `make run`, we see the following:
|
||||
|
||||

|
||||

|
||||
|
||||
It works! Now we “just” need to return from the breakpoint handler somehow so that we see the `It did not crash` message again.
|
||||
|
||||
## Returning from Exceptions
|
||||
So how do we return from exceptions? To make it easier, we look at a normal function return first:
|
||||
|
||||

|
||||

|
||||
|
||||
When calling a function, the `call` instruction pushes the return address on the stack. When the called function is finished, it can return to the parent function through the `ret` instruction, which pops the return address from the stack and then jumps to it.
|
||||
|
||||
The exception stack frame, in contrast, looks a bit different:
|
||||
|
||||

|
||||

|
||||
|
||||
Instead of pushing a return address, the CPU pushes the stack and instruction pointers (with their segment descriptors), the RFLAGS register, and an optional error code. It also aligns the stack pointer to a 16 byte boundary before pushing values.
|
||||
|
||||
@@ -204,7 +204,7 @@ Note that we also removed the `loop {}` at the end of our `breakpoint_handler` s
|
||||
### Testing
|
||||
Let's try our new `iretq` logic:
|
||||
|
||||

|
||||

|
||||
|
||||
Instead of the expected _“It did not crash”_ message after the breakpoint exception, we get a page fault. The strange thing is that our kernel tried to access address `0x1`, which should never happen. So it seems like we messed up something important.
|
||||
|
||||
@@ -414,7 +414,7 @@ Note that we no longer need to manually align the stack pointer, because we're p
|
||||
### Testing it again
|
||||
Let's test it again with our corrected `handler!` macro:
|
||||
|
||||

|
||||

|
||||
|
||||
The page fault is gone and we see the _“It did not crash”_ message again!
|
||||
|
||||
@@ -436,7 +436,7 @@ However, auto-vectorization causes a problem for us: Most of the multimedia regi
|
||||
|
||||
We don't use any multimedia registers explicitly, but the Rust compiler might auto-vectorize our code (including the exception handlers). Thus we could silently clobber the multimedia registers, which leads to the same problems as above:
|
||||
|
||||

|
||||

|
||||
|
||||
This example shows a program that is using the first three multimedia registers (`mm0` to `mm2`). At some point, an exception occurs and control is transfered to the exception handler. The exception handler uses `mm1` for its own data and thus overwrites the previous value. When the exception is resolved, the CPU continues the interrupted program again. However, the program is now corrupt since it relies on the original `mm1` value.
|
||||
|
||||
@@ -691,7 +691,7 @@ The [red zone] is an optimization of the [System V ABI] that allows functions to
|
||||
|
||||
[red zone]: http://eli.thegreenplace.net/2011/09/06/stack-frame-layout-on-x86-64#the-red-zone
|
||||
|
||||

|
||||

|
||||
|
||||
The image shows the stack frame of a function with `n` local variables. On function entry, the stack pointer is adjusted to make room on the stack for the local variables.
|
||||
|
||||
@@ -699,7 +699,7 @@ The red zone is defined as the 128 bytes below the adjusted stack pointer. The f
|
||||
|
||||
However, this optimization leads to huge problems with exceptions. Let's assume that an exception occurs while a function uses the red zone:
|
||||
|
||||

|
||||

|
||||
|
||||
The CPU and the exception handler overwrite the data in red zone. But this data is still needed by the interrupted function. So the function won't work correctly anymore when we return from the exception handler. It might fail or cause another exception, but it could also lead to strange bugs that [take weeks to debug].
|
||||
|
||||
@@ -878,7 +878,7 @@ The error code should still be `CAUSED_BY_WRITE` and the exception stack frame v
|
||||
#### Returning from Page Faults
|
||||
Let's see what happens if we comment out the trailing `loop` in our page fault handler:
|
||||
|
||||

|
||||

|
||||
|
||||
We see that the same error message is printed over and over again. Here is what happens:
|
||||
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -0,0 +1,92 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||
<svg width="17cm" height="11cm" viewBox="-60 -21 340 212" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="90" y="65.9389">
|
||||
<tspan x="90" y="65.9389"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="204" y1="70" x2="176.236" y2="70"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="185.118,65 175.118,70 185.118,75 "/>
|
||||
</g>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="208" y="72.75">
|
||||
<tspan x="208" y="72.75">Old Stack Pointer</tspan>
|
||||
</text>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="75" y="230">
|
||||
<tspan x="75" y="230"></tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="70" x2="-4" y2="70"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="190" x2="-4" y2="190"/>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="-12" y1="72.2361" x2="-12" y2="187.764"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-7,81.118 -12,71.118 -17,81.118 "/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-17,178.882 -12,188.882 -7,178.882 "/>
|
||||
</g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="0" y1="-20" x2="0" y2="0"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="170" y1="-20" x2="170" y2="0"/>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="0" width="170" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="0" width="170" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="85" y="13.125">
|
||||
<tspan x="85" y="13.125">Return Address</tspan>
|
||||
</text>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="84" y="4">
|
||||
<tspan x="84" y="4"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="0" y="20" width="170" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="20" width="170" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="85" y="33.125">
|
||||
<tspan x="85" y="33.125">Local Variable 1</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #cccccc" x="0" y="40" width="170" height="32"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x="0" y="40" width="170" height="32"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="85" y="59.125">
|
||||
<tspan x="85" y="59.125">Local Variables 2..n</tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="40" x2="170" y2="40"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="72" x2="120" y2="72"/>
|
||||
<g>
|
||||
<rect style="fill: #ff3333" x="0" y="70" width="170" height="120"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="70" width="170" height="120"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #ffffff;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="40" y="179.125">
|
||||
<tspan x="40" y="179.125">Red Zone</tspan>
|
||||
</text>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:end;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="132.75">
|
||||
<tspan x="-20" y="132.75">128 bytes</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #ffc200" x="30" y="70" width="140" height="30"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="30" y="70" width="140" height="30"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="100" y="88.125">
|
||||
<tspan x="100" y="88.125">Exception Stack Frame</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #ffe000" x="30" y="100" width="140" height="30"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="30" y="100" width="140" height="30"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="100" y="118.125">
|
||||
<tspan x="100" y="118.125">Register Backup</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #c6db97" x="30" y="130" width="140" height="30"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="30" y="130" width="140" height="30"/>
|
||||
</g>
|
||||
<text font-size="8.46654" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="100" y="147.925">
|
||||
<tspan x="100" y="147.925">Handler Function Stack Frame</tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #ff3333" x1="30" y1="70" x2="30" y2="160"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #ff3333" x1="30" y1="160" x2="170" y2="160"/>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="204" y1="160" x2="176.236" y2="160"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="185.118,155 175.118,160 185.118,165 "/>
|
||||
</g>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="208" y="162.635">
|
||||
<tspan x="208" y="162.635">New Stack Pointer</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.2 KiB |
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||
<svg width="14cm" height="9cm" viewBox="-60 -21 270 172" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="90" y="65.9389">
|
||||
<tspan x="90" y="65.9389"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="154" y1="70" x2="126.236" y2="70"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="135.118,65 125.118,70 135.118,75 "/>
|
||||
</g>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="158" y="72.75">
|
||||
<tspan x="158" y="72.75">Stack Pointer</tspan>
|
||||
</text>
|
||||
<text font-size="7.90222" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="75" y="230">
|
||||
<tspan x="75" y="230"></tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="70" x2="-4" y2="70"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="-20" y1="150" x2="-4" y2="150"/>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="-12" y1="72.2361" x2="-12" y2="147.764"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-7,81.118 -12,71.118 -17,81.118 "/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="-17,138.882 -12,148.882 -7,138.882 "/>
|
||||
</g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="0" y1="-20" x2="0" y2="0"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x1="120" y1="-20" x2="120" y2="0"/>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="0" width="120" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="0" width="120" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="13.125">
|
||||
<tspan x="60" y="13.125">Return Address</tspan>
|
||||
</text>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:start;font-family:sans-serif;font-style:normal;font-weight:normal" x="84" y="4">
|
||||
<tspan x="84" y="4"></tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="0" y="20" width="120" height="20"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="20" width="120" height="20"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="33.125">
|
||||
<tspan x="60" y="33.125">Local Variable 1</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #cccccc" x="0" y="40" width="120" height="32"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke-dasharray: 4; stroke: #000000" x="0" y="40" width="120" height="32"/>
|
||||
</g>
|
||||
<text font-size="9.03097" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="59.125">
|
||||
<tspan x="60" y="59.125">Local Variables 2..n</tspan>
|
||||
</text>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="40" x2="120" y2="40"/>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="0" y1="72" x2="120" y2="72"/>
|
||||
<g>
|
||||
<rect style="fill: #ff3333" x="0" y="70" width="120" height="80"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="70" width="120" height="80"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #ffffff;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="60" y="113.125">
|
||||
<tspan x="60" y="113.125">Red Zone</tspan>
|
||||
</text>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:end;font-family:sans-serif;font-style:normal;font-weight:normal" x="-20" y="112.75">
|
||||
<tspan x="-20" y="112.75">128 bytes</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
@@ -0,0 +1,114 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd">
|
||||
<svg width="13cm" height="4cm" viewBox="-1 -23 252 63" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="0" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="0" width="50" height="10"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="25" y="8.125">
|
||||
<tspan x="25" y="8.125">mm0</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="10" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="10" width="50" height="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="0" y="20" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="20" width="50" height="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="0" y="30" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="0" y="30" width="50" height="10"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="25" y="17.9931">
|
||||
<tspan x="25" y="17.9931">mm1</tspan>
|
||||
</text>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="25" y="28.125">
|
||||
<tspan x="25" y="28.125">mm2</tspan>
|
||||
</text>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="25" y="38.125">
|
||||
<tspan x="25" y="38.125">mm3</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="100" y="-4.44089e-15" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="100" y="-4.44089e-15" width="50" height="10"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="125" y="8.125">
|
||||
<tspan x="125" y="8.125">mm0</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #ff0000" x="100" y="10" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="100" y="10" width="50" height="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="100" y="20" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="100" y="20" width="50" height="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="100" y="30" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="100" y="30" width="50" height="10"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #ffffff;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="125" y="18.125">
|
||||
<tspan x="125" y="18.125">mm1</tspan>
|
||||
</text>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="125" y="28.125">
|
||||
<tspan x="125" y="28.125">mm2</tspan>
|
||||
</text>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="125" y="38.125">
|
||||
<tspan x="125" y="38.125">mm3</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="200" y="0" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="200" y="0" width="50" height="10"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="225" y="8.125">
|
||||
<tspan x="225" y="8.125">mm0</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<rect style="fill: #ff0000" x="200" y="10" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="200" y="10" width="50" height="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect style="fill: #00ff00" x="200" y="20" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="200" y="20" width="50" height="10"/>
|
||||
</g>
|
||||
<g>
|
||||
<rect style="fill: #dddddd" x="200" y="30" width="50" height="10"/>
|
||||
<rect style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x="200" y="30" width="50" height="10"/>
|
||||
</g>
|
||||
<text font-size="9.03111" style="fill: #ffffff;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="225" y="18.125">
|
||||
<tspan x="225" y="18.125">mm1</tspan>
|
||||
</text>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="225" y="28.125">
|
||||
<tspan x="225" y="28.125">mm2</tspan>
|
||||
</text>
|
||||
<text font-size="9.03111" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="225" y="38.125">
|
||||
<tspan x="225" y="38.125">mm3</tspan>
|
||||
</text>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="25" y="-10.0787">
|
||||
<tspan x="25" y="-10.0787">Program</tspan>
|
||||
</text>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="125" y="-15.0175">
|
||||
<tspan x="125" y="-15.0175">Exception</tspan>
|
||||
<tspan x="125" y="-5.13977">Handler</tspan>
|
||||
</text>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="50" y1="-12.8287" x2="97.7639" y2="-12.8287"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="94.882,-10.8287 98.882,-12.8287 94.882,-14.8287 "/>
|
||||
</g>
|
||||
<g>
|
||||
<line style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" x1="150" y1="-12.8287" x2="197.764" y2="-12.8287"/>
|
||||
<polyline style="fill: none; fill-opacity:0; stroke-width: 1; stroke: #000000" points="194.882,-10.8287 198.882,-12.8287 194.882,-14.8287 "/>
|
||||
</g>
|
||||
<text font-size="7.9021" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="225" y="-10.0787">
|
||||
<tspan x="225" y="-10.0787">Program</tspan>
|
||||
</text>
|
||||
<text font-size="6.77323" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="75" y="-14.737">
|
||||
<tspan x="75" y="-14.737">Exception</tspan>
|
||||
<tspan x="75" y="-6.27032">occurs</tspan>
|
||||
</text>
|
||||
<text font-size="6.77323" style="fill: #000000;text-anchor:middle;font-family:sans-serif;font-style:normal;font-weight:normal" x="175" y="-14.737">
|
||||
<tspan x="175" y="-14.737">Exception</tspan>
|
||||
<tspan x="175" y="-6.27032">resolved</tspan>
|
||||
</text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |