Class: Omnizip::Filters::BcjSparc
- Inherits:
-
FilterBase
- Object
- FilterBase
- Omnizip::Filters::BcjSparc
- Defined in:
- lib/omnizip/filters/bcj_sparc.rb
Overview
BCJ filter for SPARC executables.
This filter preprocesses SPARC machine code by converting relative addresses in CALL and BA (Branch Always) instructions to absolute addresses. SPARC uses 4-byte aligned instructions with big-endian encoding.
The filter improves compression by making branch targets position-independent.
Constant Summary collapse
- INSTRUCTION_SIZE =
Size of SPARC instruction (4 bytes, big-endian)
4- FLAG =
Flag constant for address validation
1 << 22
- OFFSET_MASK =
Mask for offset extraction
(FLAG << 3) - 1
Class Method Summary collapse
-
.metadata ⇒ Hash
Get metadata about this filter.
Instance Method Summary collapse
-
#decode(data, position = 0) ⇒ String
Decode (postprocess) SPARC executable data after decompression.
-
#encode(data, position = 0) ⇒ String
Encode (preprocess) SPARC executable data for compression.
Class Method Details
.metadata ⇒ Hash
Get metadata about this filter.
133 134 135 136 137 138 139 140 141 |
# File 'lib/omnizip/filters/bcj_sparc.rb', line 133 def { name: "BCJ-SPARC", description: "Branch converter for SPARC executables", architecture: "SPARC", alignment: 4, endian: "big", } end |
Instance Method Details
#decode(data, position = 0) ⇒ String
Decode (postprocess) SPARC executable data after decompression.
Reverses the encoding by converting absolute addresses back to relative addresses.
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/omnizip/filters/bcj_sparc.rb', line 93 def decode(data, position = 0) return data.dup if data.bytesize < INSTRUCTION_SIZE result = data.b size = data.bytesize & ~(INSTRUCTION_SIZE - 1) i = 0 pc = position - INSTRUCTION_SIZE while i < size instruction = extract_uint32_be(result, i) pc += INSTRUCTION_SIZE # Check for processed instruction pattern test_val = instruction + (5 << 29) test_val ^= 7 << 29 test_val += FLAG if test_val.nobits?(0 - (FLAG << 1)) # Extract absolute address absolute = (instruction << 2) & OFFSET_MASK # Convert to relative offset offset = absolute - pc # Encode back new_instruction = (offset & OFFSET_MASK) >> 2 new_instruction |= 1 << 30 write_uint32_be(result, i, new_instruction) end i += INSTRUCTION_SIZE end result end |
#encode(data, position = 0) ⇒ String
Encode (preprocess) SPARC executable data for compression.
Scans for CALL and BA instructions and converts relative addresses to absolute addresses.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/omnizip/filters/bcj_sparc.rb', line 48 def encode(data, position = 0) return data.dup if data.bytesize < INSTRUCTION_SIZE result = data.b size = data.bytesize & ~(INSTRUCTION_SIZE - 1) i = 0 pc = position - INSTRUCTION_SIZE while i < size instruction = extract_uint32_be(result, i) pc += INSTRUCTION_SIZE # Check for CALL or BA instruction # The check is based on specific bit patterns in SPARC ISA test_val = instruction + (5 << 29) test_val ^= 7 << 29 test_val += FLAG if test_val.nobits?(0 - (FLAG << 1)) # Extract 22-bit offset (bits 0-21) or 30-bit for CALL offset = (instruction << 2) & OFFSET_MASK # Convert to absolute address absolute = offset + pc # Encode back new_instruction = (absolute & OFFSET_MASK) >> 2 new_instruction |= 1 << 30 write_uint32_be(result, i, new_instruction) end i += INSTRUCTION_SIZE end result end |