jaulib v1.3.0
Jau Support Library (C++, Java, ..)
SectionArmAttributes.java
Go to the documentation of this file.
1/**
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2021 Gothel Software e.K.
4 * Copyright (c) 2013 Gothel Software e.K.
5 * Copyright (c) 2013 JogAmp Community.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining
8 * a copy of this software and associated documentation files (the
9 * "Software"), to deal in the Software without restriction, including
10 * without limitation the rights to use, copy, modify, merge, publish,
11 * distribute, sublicense, and/or sell copies of the Software, and to
12 * permit persons to whom the Software is furnished to do so, subject to
13 * the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be
16 * included in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26package org.jau.sys.elf;
27
28import static org.jau.sys.elf.IOUtils.getString;
29import static org.jau.sys.elf.IOUtils.readUInt32;
30import static org.jau.sys.elf.IOUtils.toHexString;
31
32import java.util.ArrayList;
33import java.util.List;
34
35import org.jau.io.Bitstream;
36
37/**
38 * ARM EABI attributes within section header {@link SectionHeader#SHT_ARM_ATTRIBUTES}.
39 * <p>
40 * References:
41 * <ul>
42 * <li>http://infocenter.arm.com/
43 * <ul>
44 * <li>ARM IHI 0044E, current through ABI release 2.09</li>
45 * <li>ARM IHI 0045D, current through ABI release 2.09</li>
46 * </ul></li>
47 * </ul>
48 * </p>
49 */
50public class SectionArmAttributes extends Section {
51 public static final byte FORMAT_VERSION_A = 0x41; // 'A';
52
53 public static enum Type {
54 /** No Value */
56 /** A Sub-Section - following the 4 byte sub section total size (tag + size + content) - byte order of the ELF file */
58 /** Null Terminated Byte-String */
61 }
62
63 /** ULEB128 Value for {@link Tag#ABI_VFP_args}: FP parameter/result passing conforms to AAPCS, BASE variant. */
64 public static final byte ABI_VFP_ARGS_IS_BASE_VARIANT = 0;
65 /** ULEB128 Value for {@link Tag#ABI_VFP_args}: FP parameter/result passing conforms to AAPCS, VFP variant. */
66 public static final byte ABI_VFP_ARGS_IS_VFP_VARIANT = 1;
67 /** ULEB128 Value for {@link Tag#ABI_VFP_args}: FP parameter/result passing conforms to custom toolchain. */
68 public static final byte ABI_VFP_ARGS_IS_CUSTOM_VARIANT = 2;
69 /** ULEB128 Value for {@link Tag#ABI_VFP_args}: FP parameter/result passing conforms to both , BASE and VFP variant. */
70 public static final byte ABI_VFP_ARGS_IS_BOTH_BASE_AND_VFP_VARIANT = 3;
71
72 /**
73 * Returns true if value is either {@link #ABI_VFP_ARGS_IS_VFP_VARIANT} or {@link #ABI_VFP_ARGS_IS_BOTH_BASE_AND_VFP_VARIANT}
74 * @param v ULEB128 Value from {@link Tag#ABI_VFP_args} attribute
75 */
76 public static final boolean abiVFPArgsAcceptsVFPVariant(final byte v) {
78 }
79
80 public static enum Tag {
111 compatibility ( 32, Type.NTBS ), /** with each byte interpreted as an ULEB128 with closing EOS */
117 nodefaults( 64, Type.ULEB128 ), /* value ignored */
123 MPextension_use_legacy( 70, Type.ULEB128 )
125
126 public final int id;
127 public final Type type;
128
129 /** Slow O(n) transition of a native tag value to a Tag. */
130 public static Tag get(final int id) {
131 final Tag[] tags = Tag.values();
132 final int tag_count = tags.length;
133 for(int i=0; i < tag_count; i++) {
134 if( tags[i].id == id ) {
135 return tags[i];
136 }
137 }
138 return null;
139 }
140
141 Tag(final int id, final Type type){
142 this.id = id;
143 this.type = type;
144 }
145 }
146
147 public static class Attribute {
148 public final Tag tag;
149 private final Object value;
150
151 Attribute(final Tag tag, final Object value) {
152 this.tag = tag;
153 this.value = value;
154 }
155
156 public final boolean isNTBS() {
157 return Type.NTBS == tag.type;
158 }
159 public final String getNTBS() {
160 if( Type.NTBS == tag.type ) {
161 return (String) value;
162 }
163 throw new IllegalArgumentException("Not NTBS but "+tag.type);
164 }
165
166 public final boolean isULEB128() {
167 return Type.ULEB128 == tag.type;
168 }
169 public final byte getULEB128() {
170 if( Type.ULEB128== tag.type ) {
171 return ((Byte) value).byteValue();
172 }
173 throw new IllegalArgumentException("Not ULEB128 but "+tag.type);
174 }
175
176 @Override
177 public String toString() {
178 return tag+" = "+value;
179 }
180 }
181
182 public static class VendorAttributes {
183 public final String vendor;
184 public final List<Attribute> attributes;
185
186 VendorAttributes(final String vendor, final List<Attribute> attributes) {
187 this.vendor = vendor;
188 this.attributes = attributes;
189 }
190
191 @Override
192 public String toString() {
193 return vendor + attributes.toString();
194 }
195 }
196 public final List<VendorAttributes> vendorAttributesList;
197
198 SectionArmAttributes(final SectionHeader sh, final byte[] data, final int offset, final int length) throws IndexOutOfBoundsException, IllegalArgumentException {
199 super(sh, data, offset, length);
200 this.vendorAttributesList = parse(sh, data, offset, length);
201 }
202
203 @Override
204 public String toString() {
205 return "SectionArmAttributes["+super.toSubString()+", "+vendorAttributesList.toString()+"]";
206 }
207
208 public final Attribute get(final Tag tag) {
209 for(int i=0; i<vendorAttributesList.size(); i++) {
210 final List<Attribute> attributes = vendorAttributesList.get(i).attributes;
211 for(int j=0; j<attributes.size(); j++) {
212 final Attribute a = attributes.get(j);
213 if( a.tag == tag ) {
214 return a;
215 }
216 }
217 }
218 return null;
219 }
220
221 public final List<Attribute> get(final String vendor) {
222 return get(vendorAttributesList, vendor);
223 }
224
225 static final List<Attribute> get(final List<VendorAttributes> vendorAttributesList, final String vendor) {
226 for(int i=0; i<vendorAttributesList.size(); i++) {
227 final VendorAttributes vas = vendorAttributesList.get(i);
228 if( vas.vendor.equals(vendor) ) {
229 return vas.attributes;
230 }
231 }
232 return null;
233 }
234
235 /**
236 * @param sh TODO
237 * @param in byte source buffer to parse
238 * @param offset offset within byte source buffer to start parsing
239 * @param remaining remaining numbers of bytes to parse beginning w/ <code>sb_off</code>,
240 * which shall not exceed <code>sb.length - offset</code>.
241 * @throws IndexOutOfBoundsException if <code>offset + remaining > sb.length</code>.
242 * @throws IllegalArgumentException if section parsing failed, i.e. incompatible version or data.
243 */
244 static List<VendorAttributes> parse(final SectionHeader sh, final byte[] in, final int offset, final int remaining) throws IndexOutOfBoundsException, IllegalArgumentException {
245 Bitstream.checkBounds(in, offset, remaining);
246 int i = offset;
247 if( FORMAT_VERSION_A != in[ i ] ) {
248 throw new IllegalArgumentException("ShArmAttr: Not version A, but: "+toHexString(in[i]));
249 }
250 i++;
251
252 final List<VendorAttributes> vendorAttributesList = new ArrayList<VendorAttributes>();
253 final boolean isBigEndian = sh.eh2.eh1.isBigEndian();
254
255 while(i < remaining) {
256 final int i_pre = i;
257 final int secLen = readUInt32(isBigEndian, in, i); /* total section size: 4 + string + content, i.e. offset to next section */
258 i+=4;
259
260 final String vendor;
261 {
262 final int[] i_post = new int[] { 0 };
263 vendor = getString(in, i, secLen - 4, i_post);
264 i = i_post[0];
265 }
266
267 final List<Attribute> attributes = new ArrayList<Attribute>();
268
269 while(i < secLen) {
270 final int[] i_post = new int[] { 0 };
271 parseSub(isBigEndian, in, i, secLen - i, i_post, attributes);
272 i = i_post[0];
273 }
274
275 if( i_pre + secLen != i ) {
276 throw new IllegalArgumentException("ShArmAttr: Section length count mismatch, expected "+(i_pre + secLen)+", has "+i);
277 }
278
279 final List<Attribute> mergeAttribs = get(vendorAttributesList, vendor);
280 if( null != mergeAttribs ) {
281 mergeAttribs.addAll(attributes);
282 } else {
283 vendorAttributesList.add(new VendorAttributes(vendor, attributes));
284 }
285 }
286
288 }
289
290 /**
291 * @param isBigEndian TODO
292 * @param in byte source buffer to parse
293 * @param offset offset within byte source buffer to start parsing
294 * @param remaining remaining numbers of bytes to parse beginning w/ <code>sb_off</code>,
295 * which shall not exceed <code>sb.length - offset</code>.
296 * @throws IndexOutOfBoundsException if <code>offset + remaining > sb.length</code>.
297 * @throws IllegalArgumentException if section parsing failed, i.e. incompatible version or data.
298 */
299 private static void parseSub(final boolean isBigEndian, final byte[] in, final int offset, final int remaining,
300 final int[] offset_post, final List<Attribute> attributes)
301 throws IndexOutOfBoundsException, IllegalArgumentException
302 {
303 Bitstream.checkBounds(in, offset, remaining);
304
305 // Starts w/ sub-section Tag
306 int i = offset;
307 final int i_sTag = in[i++];
308 final Tag sTag = Tag.get(i_sTag);
309 if( null == sTag ) {
310 throw new IllegalArgumentException("ShArmAttr: Invalid Sub-Section tag (NaT): "+i_sTag);
311 }
312 final int subSecLen; // sub section total size (tag + size + content)
313 switch(sTag) {
314 case File:
315 case Section:
316 case Symbol:
317 subSecLen = readUInt32(isBigEndian, in, i);
318 i+=4;
319 break;
320 default:
321 throw new IllegalArgumentException("ShArmAttr: Invalid Sub-Section tag: "+sTag);
322 }
323 if( Tag.File == sTag ) {
324 while( i < offset + subSecLen ) {
325 final int i_tag = in[i++];
326 final Tag tag = Tag.get(i_tag);
327 if( null == tag ) {
328 throw new IllegalArgumentException("ShArmAttr: Invalid Attribute tag (NaT): "+i_tag);
329 }
330 switch(tag.type) {
331 case NTBS:
332 {
333 final int[] i_post = new int[] { 0 };
334 final String value = getString(in, i, subSecLen + offset - i, i_post);
335 attributes.add(new Attribute(tag, value));
336 i = i_post[0];
337 }
338 break;
339 case ULEB128:
340 {
341 final byte value = in[i++];
342 attributes.add( new Attribute( tag, Byte.valueOf(value) ) );
343 }
344 break;
345 default:
346 throw new IllegalArgumentException("ShArmAttr: Invalid Attribute tag: "+tag);
347 }
348 }
349 }
350 offset_post[0] = offset + subSecLen;
351 }
352}
final boolean isBigEndian()
Returns whether the processor's data encoding is ELFDATA2MSB.
final ElfHeaderPart1 eh1
Public access to the elf header part-1 (CPU/ABI independent read)
ARM EABI attributes within section header SectionHeader#SHT_ARM_ATTRIBUTES.
static final byte ABI_VFP_ARGS_IS_BOTH_BASE_AND_VFP_VARIANT
ULEB128 Value for Tag#ABI_VFP_args: FP parameter/result passing conforms to both ,...
static final byte ABI_VFP_ARGS_IS_CUSTOM_VARIANT
ULEB128 Value for Tag#ABI_VFP_args: FP parameter/result passing conforms to custom toolchain.
final List< VendorAttributes > vendorAttributesList
static final byte ABI_VFP_ARGS_IS_BASE_VARIANT
ULEB128 Value for Tag#ABI_VFP_args: FP parameter/result passing conforms to AAPCS,...
static final boolean abiVFPArgsAcceptsVFPVariant(final byte v)
Returns true if value is either ABI_VFP_ARGS_IS_VFP_VARIANT or ABI_VFP_ARGS_IS_BOTH_BASE_AND_VFP_VARI...
static final byte ABI_VFP_ARGS_IS_VFP_VARIANT
ULEB128 Value for Tag#ABI_VFP_args: FP parameter/result passing conforms to AAPCS,...
ELF ABI Section Header.
final ElfHeaderPart2 eh2
Public access to the elf header.
SectionHeader sh
Definition: Section.java:29
CPU_unaligned_access
with each byte interpreted as an ULEB128 with closing EOS
SubSection
A Sub-Section - following the 4 byte sub section total size (tag + size + content) - byte order of th...