Tockloader Bug Investigation Init Fn Size And Protected Size Discrepancies
Hey guys! Ever stumbled upon a tech puzzle that just makes you scratch your head? Well, Iβve got one for you today! We're diving deep into the world of TockOS, specifically the Tockloader, and uncovering some intriguing differences between the Python and Rust versions when it comes to reading TBF (Tock Binary Format) headers. It's like comparing notes from two different students and finding some subtle, yet significant, variations. So, buckle up, and letβs get our geek on!
The Mystery: Differing Outputs in Init Fn Size and Protected Size
Our main focus today is on a peculiar issue observed when using tockloader info
. This command, a handy tool for inspecting Tock applications, reveals a discrepancy in the output between the Python version (tockloader.py
) and the Rust version (tockloader-rs
). The variances pop up in the TLV (Type-Length-Value) headers, particularly in the init_fn_size
and protected_size
fields. It's like spotting a typo in a critical document β it might not break everything, but it definitely raises an eyebrow. To really get our hands dirty, Iβve compiled the latest libtock-c
with the c-hello
example. This gives us a consistent test case to compare the outputs.
Diving into the Python Output
Letβs kick things off by examining what the Python version spits out. When we run python3 -m tockloader.main info
, we get a detailed breakdown of the application. The output includes crucial information like the application name, version, and size. But the interesting bits for our case are within the TLV headers. Specifically, the Python output shows the init_fn_offset
as 41 (0x29) and the protected_size
as 0. This is important. Remember these numbers, guys, because theyβre about to get a twist.
(.venv) localhost ~/Work/tockloader $ python3 -m tockloader.main info
[INFO ] Using openocd channel to communicate with the board.
[INFO ] Using settings from KNOWN_BOARDS["microbit_v2"]
tockloader version: 1.15.0.dev1
[STATUS ] Showing all properties of the board...
Apps:
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β App 0 |
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Name: c_hello
Version: 0
Enabled: True
Sticky: False
Total Size in Flash: 4096 bytes
Address in Flash: 0x40000
TBF version : 2 [0x0 ] [0x40000 ]
header_size : 76 0x4c
total_size : 4096 0x1000
checksum : 0x65502739
flags : 1 0x1
enabled : Yes
sticky : No
TLV: Main (1) [0x10 ] [0x40010 ]
init_fn_offset : 41 0x29
protected_size : 0 0x0
minimum_ram_size : 4580 0x11e4
TLV: Program (9) [0x20 ] [0x40020 ]
init_fn_offset : 41 0x29
protected_size : 0 0x0
minimum_ram_size: 4580 0x11e4
binary_end_offset : 1076 0x434
app_version : 0 0x0
TLV: Package Name (3) [0x38 ] [0x40038 ]
package_name : c_hello
TLV: Kernel Version (8) [0x44 ] [0x40044 ]
kernel_major : 2
kernel_minor : 0
kernel version : ^2.0
Footer
footer_size : 3020 0xbcc
Footer TLV: Credentials (128) [0x0 ] [0x40434 ]
Type: Reserved (0)
Length: 3012
Attributes:
Bootloader version: v1.1.1
Kernel Attributes [0x0 ] [0x40000 ]
sentinel : TOCK [-0x4 ] [0x3fffc ]
version : 1 [-0x8 ] [0x3fff8 ]
KATLV: App Memory (0x101) [-0x14] [0x3ffec ]
app_memory_start : 536893380 0x200057c4
app_memory_len : 108604 0x1a83c
KATLV: Kernel Binary (0x102) [-0x20] [0x3ffe0 ]
kernel_binary_start : 32768 0x8000
kernel_binary_len : 536846336 0x1fffa000
The Rust Version's Perspective
Now, letβs switch gears and peek at the output from the Rust version. Running cargo run -- info --board microbit-v2
gives us a similar, yet distinctly different, view. The Rust version reports the init_fn_offset
as 117 and the protected_size
as 76. Woah! Thatβs quite a jump from the Python versionβs 41 and 0, isn't it? This difference is the heart of our puzzle. It suggests that the two versions are interpreting the TBF headers in a slightly different way. It's like reading the same map but ending up at slightly different locations.
(.venv) localhost ~/Work/tockloader-rs $ cargo run -- info --board microbit-v2
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.18s
Running `target/debug/tockloader info --board microbit-v2`
> Which debug probe do you want to use? "BBC micro:bit CMSIS-DAP" -- 0d28:0204:9904360259004e45005e300300000027000000009796990b (CMSIS-DAP)
ββββββββββββββββββ
β App_0 β
ββββββββββββββββββ
Name: c_hello
Version: 0
Enabled: true
Stricky: false
Total_Size: 4096
Address in Flash: 262144
TBF version: 0
header_size: 76
total_size: 4096
checksum: 1699751737
flags:
enabled: true
sticky: false
TVL: Main (1)
init_fn_offset: 117
protected_size: 76
minimum_ram_size: 4580
TVL: Program (9)
init_fn_offset: 117
protected_size: 76
minimum_ram_size: 4580
binary_end_offset: 1076
app_version: 0
TVL: Package Name (3)
package_name: c_hello
TVL: Kernel Version (8)
kernel_major: 2
kernel_minor: 0
Footer
footer_size: 3020
Footer [0] TVL: Credentials
Type: Reserved
Length: 3012
Kernel Attributes
Sentinel: TOCK
Version: 1
KATLV: APP Memory
app_memory_start: 536893380
app_memory_len: 108604
KATLV: Kernel Binary
kernel_binary_start: 32768
kernel_binary_len: 536846336
Potential Culprits: Where Could the Bug Be Hiding?
So, where do we even start looking for the cause of this discrepancy? Well, one potential suspect is the tbf-parser library. There's a mention of a past encounter with similar issues, specifically in #29. It might be worth revisiting that to see if there's a connection. The other possibility is that the issue lies in how we read the TBF headers within the lib
of each version. Itβs like having two different translators for the same language β they might interpret some nuances differently. Itβs also crucial to ensure that the TBF format is being parsed correctly. This format dictates how the application metadata is structured, and any misinterpretation here could lead to incorrect values for fields like init_fn_offset
and protected_size
.
The Role of TBF Parser Library
The TBF parser library is crucial in interpreting the binary format of Tock applications. If this library has a bug, it could lead to misreading the init_fn_size
and protected_size
fields. Checking past issues, like #29, might reveal similar problems or fixes that could apply here. Itβs like detective work, where past cases can give us clues to solve the current mystery.
Reading TBF Headers in Lib
Another place where the issue might be hiding is in the logic for reading TBF headers within each version of Tockloader. The Python and Rust versions might have slight differences in how they interpret the header structure, leading to the observed discrepancies. This is where a careful comparison of the code in both versions is essential. It's like comparing the recipes of two chefs β they might use the same ingredients but end up with slightly different dishes.
Time to Roll Up Our Sleeves: Replicating the Bug and Finding a Fix
Now comes the fun part β the investigation! The first step is to replicate the bug. Can you, guys, reproduce the same output differences on your end? If we can confirm that this isnβt just a one-off issue, we know weβre on the right track. Once weβve got a solid reproduction, itβs time to dive into the code and start hunting for the root cause. This might involve stepping through the parsing logic, comparing the Python and Rust implementations, and maybe even dusting off our TBF format specification knowledge.
Verifying the Bug
To effectively tackle this issue, we need to ensure that it can be consistently reproduced across different environments. Replicating the bug is a critical step in confirming its existence and understanding its scope. This involves running the same commands (tockloader info
in both Python and Rust) on the same application binary and verifying that the output discrepancies persist.
Sending a PR
If you, guys, think youβve spotted the culprit and have a fix in mind, donβt hesitate to send a PR (Pull Request)! This is how open-source projects thrive β through collaboration and community contributions. A well-documented PR, explaining the issue, the fix, and how it was tested, is gold. It's like sharing your secret recipe with the world, but for code!
Let's Get to the Bottom of This!
So, there you have it β a tech mystery wrapped in a TBF header. The differing init_fn_size
and protected_size
fields between the Python and Rust versions of Tockloader are definitely intriguing. Itβs a challenge that calls for some careful investigation, a bit of code sleuthing, and maybe a dash of community collaboration. If you are familiar with embedded systems, TockOS, and binary formats, your expertise can significantly contribute to solving this issue. Remember, every bug squashed makes the software world a little bit better. Letβs dive in and see what we can uncover, guys!