From 2b08069b0a3c767354473a5c08f91df9df52a41a Mon Sep 17 00:00:00 2001 From: Eugene Shamis Date: Tue, 25 Nov 2025 11:20:42 -0500 Subject: [PATCH 1/2] Added total size padding override. Documented unused parameter --- README.md | 54 ++++++++++++++++++++++++++------------------------ src/cmdline.rs | 11 ++++++++-- src/convert.rs | 30 +++++++++++++++++----------- src/main.rs | 3 ++- 4 files changed, 57 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index 838bc48..30097e2 100644 --- a/README.md +++ b/README.md @@ -16,32 +16,34 @@ Arguments: ... application file(s) to package Options: - -v, --verbose Be verbose - --deterministic Produce a deterministic TAB file - --disable Mark the app as disabled in the TBF flags - --app-version Set the version number [default: 0] - --minimum-ram-size in bytes - -o, --output-file output file name [default: TockApp.tab] - -n, --package-name package name - --stack in bytes - --app-heap in bytes [default: 1024] - --kernel-heap in bytes [default: 1024] - --protected-region-size Size of the protected region (including headers) - --permissions ... A list of driver numbers and allowed commands - --write_id A storage ID used for writing data - --read_ids ... Storage IDs that this app is allowed to read - --access_ids ... Storage IDs that this app is allowed to write - --short-id ShortId to request in the app's header - --kernel-major The kernel version that the app requires - --kernel-minor The minimum kernel minor version that the app requires - --supported-boards comma separated list of boards this app is compatible with - --minimum-footer-size Minimum number of bytes to reserve space for in the footer [default: 0] - --sha256 Add a SHA256 hash credential to each TBF - --sha384 Add a SHA384 hash credential to each TBF - --sha512 Add a SHA512 hash credential to each TBF - --rsa4096-private Add an 4096-bit RSA signature credential using this private key - -h, --help Print help - -V, --version Print version + -v, --verbose Be verbose + --deterministic Produce a deterministic TAB file + --disable Mark the app as disabled in the TBF flags + --app-version Set the version number [default: 0] + --minimum-ram-size in bytes - has no effect, kept for backwards compatibility + --total-size-padding pad the total size of the binary to the multiple of . If not specified, use the architecture default + -o, --output-file output file name [default: TockApp.tab] + -n, --package-name package name + --stack in bytes + --app-heap in bytes [default: 1024] + --kernel-heap in bytes [default: 1024] + --protected-region-size Size of the protected region (including headers) + --permissions ... A list of driver numbers and allowed commands + --write_id A storage ID used for writing data + --read_ids ... Storage IDs that this app is allowed to read + --access_ids ... Storage IDs that this app is allowed to write + --short-id ShortId to request in the app's header + --kernel-major The kernel version that the app requires + --kernel-minor The minimum kernel minor version that the app requires + --supported-boards comma separated list of boards this app is compatible with + --minimum-footer-size Minimum number of bytes to reserve space for in the footer [default: 0] + --sha256 Add a SHA256 hash credential to each TBF + --sha384 Add a SHA384 hash credential to each TBF + --sha512 Add a SHA512 hash credential to each TBF + --rsa4096-private Add an 4096-bit RSA signature credential using this private key + --ecdsa-nist-p256-private Add an ECDSA NIST P256 signature credential using this private key + -h, --help Print help + -V, --version Print version ``` For example, converting a "blink" app from a compiled .elf file (for a Cortex-M4 diff --git a/src/cmdline.rs b/src/cmdline.rs index 761ad01..3b9a078 100644 --- a/src/cmdline.rs +++ b/src/cmdline.rs @@ -64,12 +64,19 @@ pub struct Opt { #[arg( long = "minimum-ram-size", id = "min-ram-size", - help = "in bytes", + help = "in bytes - has no effect, kept for backwards compatibility", conflicts_with = "stack-size", conflicts_with = "heap-size", conflicts_with = "kernel-heap-size" )] - pub minimum_stack_size: Option, + pub _minimum_stack_size: Option, + + #[arg( + long = "total-size-padding", + id = "padding", + help = "pad the total size of the binary to the multiple of . If not specified, use the architecture default", + )] + pub total_size_padding: Option, #[arg( long = "output-file", diff --git a/src/convert.rs b/src/convert.rs index 80e8830..4b7f85c 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -143,6 +143,7 @@ pub fn elf_to_tbf( sha512: bool, rsa4096_private_key: Option, ecdsa_nist_p256_private_key: Option, + trailing_padding_requested: Option, ) -> io::Result<()> { let package_name = package_name.unwrap_or_default(); @@ -189,18 +190,23 @@ pub fn elf_to_tbf( TotalSizeMultiple(usize), } - // Add trailing padding for certain architectures. - // - // - ARM: make sure the entire TBF is a power of 2 to make configuring the - // MPU easy. - // - RISC_V: make sure the entire TBF is a multiple of 4 to meet TBF - // alignment requirements. - // - x86: use 4k padding to match page size. - let trailing_padding = match elf_file.ehdr.e_machine { - elf::abi::EM_ARM => Some(TrailingPadding::TotalSizePowerOfTwo), - elf::abi::EM_RISCV => Some(TrailingPadding::TotalSizeMultiple(4)), - elf::abi::EM_386 => Some(TrailingPadding::TotalSizeMultiple(4096)), - _ => None, + let trailing_padding = if let Some(trailing_padding_requested) = trailing_padding_requested { + // User specified padding override. + Some(TrailingPadding::TotalSizeMultiple(trailing_padding_requested as usize)) + } else { + // Add default trailing padding for certain architectures. + // + // - ARM: make sure the entire TBF is a power of 2 to make configuring the + // MPU easy. + // - RISC_V: make sure the entire TBF is a multiple of 4 to meet TBF + // alignment requirements. + // - x86: use 4k padding to match page size. + match elf_file.ehdr.e_machine { + elf::abi::EM_ARM => Some(TrailingPadding::TotalSizePowerOfTwo), + elf::abi::EM_RISCV => Some(TrailingPadding::TotalSizeMultiple(4)), + elf::abi::EM_386 => Some(TrailingPadding::TotalSizeMultiple(4096)), + _ => None, + } }; //////////////////////////////////////////////////////////////////////////// diff --git a/src/main.rs b/src/main.rs index e88bf3f..40acc06 100644 --- a/src/main.rs +++ b/src/main.rs @@ -147,10 +147,11 @@ fn main() { opt.sha512_enable, opt.rsa4096_private_key.clone(), opt.ecdsa_nist_p256_private_key.clone(), + opt.total_size_padding, ) .unwrap(); if opt.verbose { - println!(""); + println!(); } match outfile.write_all(output_vector.as_ref()) { From e73d10f41cdc56d125fe405c33c3dd3448cf9d02 Mon Sep 17 00:00:00 2001 From: Eugene Shamis Date: Wed, 25 Feb 2026 18:16:23 -0500 Subject: [PATCH 2/2] Replace CLI total-size-padding with ELF symbol lookup Instead of a --total-size-padding command-line option that applies uniformly to every ELF, read a per-binary `tbf_total_size_padding` symbol from the ELF's symbol table. This is looked up in the same pass as `tbf_protected_region_size` and, when present, overrides the architecture-default trailing padding. --- README.md | 18 +++++++++++- src/cmdline.rs | 7 ----- src/convert.rs | 76 ++++++++++++++++++++++++++++---------------------- src/main.rs | 1 - 4 files changed, 59 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 30097e2..6d3f7fd 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,6 @@ Options: --disable Mark the app as disabled in the TBF flags --app-version Set the version number [default: 0] --minimum-ram-size in bytes - has no effect, kept for backwards compatibility - --total-size-padding pad the total size of the binary to the multiple of . If not specified, use the architecture default -o, --output-file output file name [default: TockApp.tab] -n, --package-name package name --stack in bytes @@ -169,6 +168,23 @@ increase the size of the protected region to make the start of the TBF header at an address aligned to 256 bytes when the application binary is at its correct fixed address. +#### Trailing Padding (Total Size Alignment) + +elf2tab adds trailing padding to each TBF to satisfy architecture-specific +alignment constraints: + +- **ARM**: total size is padded to a power of 2 (for MPU region alignment). +- **RISC-V**: total size is padded to a multiple of 4 (TBF alignment + requirement). +- **x86**: total size is padded to a multiple of 4096 (page size). + +An application can override the default padding by defining a +`tbf_total_size_padding` symbol in its ELF file. When present, the symbol's +value is interpreted as a byte multiple, and the total TBF size will be padded +to a multiple of that value instead of the architecture default. This is useful, +for example, when a platform requires a different alignment than the +architecture-level default. + #### Syscall Permissions elf2tab allows explicitly specifying the syscalls that an app is allowed to diff --git a/src/cmdline.rs b/src/cmdline.rs index 3b9a078..94c1f31 100644 --- a/src/cmdline.rs +++ b/src/cmdline.rs @@ -71,13 +71,6 @@ pub struct Opt { )] pub _minimum_stack_size: Option, - #[arg( - long = "total-size-padding", - id = "padding", - help = "pad the total size of the binary to the multiple of . If not specified, use the architecture default", - )] - pub total_size_padding: Option, - #[arg( long = "output-file", short = 'o', diff --git a/src/convert.rs b/src/convert.rs index 4b7f85c..1fe3d80 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -143,7 +143,6 @@ pub fn elf_to_tbf( sha512: bool, rsa4096_private_key: Option, ecdsa_nist_p256_private_key: Option, - trailing_padding_requested: Option, ) -> io::Result<()> { let package_name = package_name.unwrap_or_default(); @@ -190,23 +189,21 @@ pub fn elf_to_tbf( TotalSizeMultiple(usize), } - let trailing_padding = if let Some(trailing_padding_requested) = trailing_padding_requested { - // User specified padding override. - Some(TrailingPadding::TotalSizeMultiple(trailing_padding_requested as usize)) - } else { - // Add default trailing padding for certain architectures. - // - // - ARM: make sure the entire TBF is a power of 2 to make configuring the - // MPU easy. - // - RISC_V: make sure the entire TBF is a multiple of 4 to meet TBF - // alignment requirements. - // - x86: use 4k padding to match page size. - match elf_file.ehdr.e_machine { - elf::abi::EM_ARM => Some(TrailingPadding::TotalSizePowerOfTwo), - elf::abi::EM_RISCV => Some(TrailingPadding::TotalSizeMultiple(4)), - elf::abi::EM_386 => Some(TrailingPadding::TotalSizeMultiple(4096)), - _ => None, - } + // Add trailing padding for certain architectures. + // + // - ARM: make sure the entire TBF is a power of 2 to make configuring the + // MPU easy. + // - RISC_V: make sure the entire TBF is a multiple of 4 to meet TBF + // alignment requirements. + // - x86: use 4k padding to match page size. + // + // This default may be overridden by a `tbf_total_size_padding` symbol + // in the ELF file. + let arch_trailing_padding = match elf_file.ehdr.e_machine { + elf::abi::EM_ARM => Some(TrailingPadding::TotalSizePowerOfTwo), + elf::abi::EM_RISCV => Some(TrailingPadding::TotalSizeMultiple(4)), + elf::abi::EM_386 => Some(TrailingPadding::TotalSizeMultiple(4096)), + _ => None, }; //////////////////////////////////////////////////////////////////////////// @@ -476,26 +473,37 @@ pub fn elf_to_tbf( // Adjust the protected region size to make fixed address work //////////////////////////////////////////////////////////////////////////// - // Applications can hint a desired protected region size to elf2tab by - // defining a special `tbf_protected_region_size` symbol: - let protected_region_size_symbol = + // Applications can hint configuration to elf2tab by defining special + // symbols: + // + // - `tbf_protected_region_size`: desired protected region size. + // - `tbf_total_size_padding`: pad total size to a multiple of this value, + // overriding the architecture default. + let (protected_region_size_symbol, total_size_padding_symbol) = if let Ok(Some((symtab, sym_strtab))) = elf_file.symbol_table() { - // We are looking for the `tbf_protected_region_size` symbol and its - // value. If it exists, we can use it as a hint for the protected - // region size. - symtab - .iter() - .find(|sym| { - let name = sym_strtab - .get(sym.st_name as usize) - .expect("Failed to parse symbol name"); - name == "tbf_protected_region_size" - }) - .map(|tbf_header_sym| tbf_header_sym.st_value as u32) + let mut prs = None; + let mut tsp = None; + for sym in symtab.iter() { + let name = sym_strtab + .get(sym.st_name as usize) + .expect("Failed to parse symbol name"); + if name == "tbf_protected_region_size" { + prs = Some(sym.st_value as u32); + } else if name == "tbf_total_size_padding" { + tsp = Some(sym.st_value as usize); + } + } + (prs, tsp) } else { - None + (None, None) }; + // Override trailing padding if specified in the ELF via the + // `tbf_total_size_padding` symbol. + let trailing_padding = total_size_padding_symbol + .map(TrailingPadding::TotalSizeMultiple) + .or(arch_trailing_padding); + // Determine the protected region size by checking the following sources in // this order: // diff --git a/src/main.rs b/src/main.rs index 40acc06..6457ee7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -147,7 +147,6 @@ fn main() { opt.sha512_enable, opt.rsa4096_private_key.clone(), opt.ecdsa_nist_p256_private_key.clone(), - opt.total_size_padding, ) .unwrap(); if opt.verbose {