-
Notifications
You must be signed in to change notification settings - Fork 29
ctf: Add new field classes to complete ctf2 parsing #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| /********************************************************************** | ||
| * Copyright (c) 2026 École Polytechnique de Montréal | ||
| * | ||
| * All rights reserved. This program and the accompanying materials are | ||
| * made available under the terms of the Eclipse Public License 2.0 which | ||
| * accompanies this distribution, and is available at | ||
| * https://www.eclipse.org/legal/epl-2.0/ | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| **********************************************************************/ | ||
| package org.eclipse.tracecompass.ctf.core.event.types; | ||
|
|
||
| import java.nio.ByteOrder; | ||
|
|
||
| import org.eclipse.jdt.annotation.NonNull; | ||
| import org.eclipse.tracecompass.ctf.core.CTFException; | ||
| import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer; | ||
| import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; | ||
|
|
||
| /** | ||
| * A CTF declaration of a boolean field | ||
| * | ||
| * It declares a certain amount of bits as a boolean value. | ||
| * | ||
| * @since 5.2 | ||
| * @author Arnaud Fiorini | ||
| */ | ||
| public class BooleanDeclaration extends Declaration { | ||
|
|
||
| private int fLength; | ||
| private long fAlignment; | ||
| private ByteOrder fByteOrder; | ||
|
|
||
| /** | ||
| * @param length | ||
| * the size of the boolean field | ||
| * @param byteOrder | ||
| * the order in which the bytes should be read | ||
| * @param alignment | ||
| * alignment of the first bit of field relative to the beginning | ||
| * of the packet | ||
| */ | ||
| public BooleanDeclaration(int length, ByteOrder byteOrder, long alignment) { | ||
| fLength = length; | ||
| fByteOrder = byteOrder; | ||
| fAlignment = alignment; | ||
| } | ||
|
|
||
| @Override | ||
| public @NonNull Definition createDefinition(IDefinitionScope definitionScope, @NonNull String fieldName, @NonNull BitBuffer input) throws CTFException { | ||
| ByteOrder byteOrder = input.getByteOrder(); | ||
| input.setByteOrder(fByteOrder); | ||
| boolean value = read(input); | ||
| input.setByteOrder(byteOrder); | ||
| return new BooleanDefinition(this, definitionScope, fieldName, value); | ||
| } | ||
|
|
||
| private boolean read(BitBuffer input) throws CTFException { | ||
| for (int i = 0; i < fLength; i++) { | ||
| if (input.get(Math.min(64, fLength - i * 64), false) != 0) { | ||
| return true; | ||
| } | ||
| } | ||
|
Comment on lines
+58
to
+63
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fix chunk iteration in boolean bit reader. The loop advances by 1 bit-index but subtracts Proposed fix private boolean read(BitBuffer input) throws CTFException {
- for (int i = 0; i < fLength; i++) {
- if (input.get(Math.min(64, fLength - i * 64), false) != 0) {
+ int remaining = fLength;
+ while (remaining > 0) {
+ int chunkSize = Math.min(64, remaining);
+ if (input.get(chunkSize, false) != 0) {
return true;
}
+ remaining -= chunkSize;
}
return false;
}🤖 Prompt for AI Agents |
||
| return false; | ||
| } | ||
|
|
||
| @Override | ||
| public long getAlignment() { | ||
| return fAlignment; | ||
| } | ||
|
|
||
| @Override | ||
| public int getMaximumSize() { | ||
| return fLength; | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isBinaryEquivalent(IDeclaration other) { | ||
| if (this == other) { | ||
| return true; | ||
| } | ||
| if (other == null) { | ||
| return false; | ||
| } | ||
| if (getClass() != other.getClass()) { | ||
| return false; | ||
| } | ||
| return fLength == other.getMaximumSize(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| /********************************************************************** | ||
| * Copyright (c) 2026 École Polytechnique de Montréal | ||
| * | ||
| * All rights reserved. This program and the accompanying materials are | ||
| * made available under the terms of the Eclipse Public License 2.0 which | ||
| * accompanies this distribution, and is available at | ||
| * https://www.eclipse.org/legal/epl-2.0/ | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| **********************************************************************/ | ||
| package org.eclipse.tracecompass.ctf.core.event.types; | ||
|
|
||
| import org.eclipse.jdt.annotation.NonNull; | ||
| import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; | ||
|
|
||
| /** | ||
| * A CTF2 boolean definition. | ||
| * | ||
| * The definition of a boolean field class in ctf2 | ||
| * | ||
| * @author Arnaud Fiorini | ||
| * @since 5.2 | ||
| */ | ||
| public class BooleanDefinition extends SimpleDatatypeDefinition { | ||
|
|
||
| private final boolean fValue; | ||
|
|
||
| /** | ||
| * Constructor | ||
| * | ||
| * @param declaration | ||
| * the parent declaration | ||
| * @param definitionScope | ||
| * the parent scope | ||
| * @param fieldName | ||
| * the field name | ||
| * @param value | ||
| * the field value | ||
| */ | ||
| public BooleanDefinition(@NonNull IDeclaration declaration, IDefinitionScope definitionScope, @NonNull String fieldName, boolean value) { | ||
| super(declaration, definitionScope, fieldName); | ||
| fValue = value; | ||
| } | ||
|
|
||
| /** | ||
| * @return boolean value of the field | ||
| */ | ||
| public boolean getValue() { | ||
| return fValue; | ||
| } | ||
|
|
||
| @Override | ||
| public BooleanDeclaration getDeclaration() { | ||
| return (BooleanDeclaration) super.getDeclaration(); | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| return String.valueOf(fValue); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| /********************************************************************** | ||
| * Copyright (c) 2026 École Polytechnique de Montréal | ||
| * | ||
| * All rights reserved. This program and the accompanying materials are | ||
| * made available under the terms of the Eclipse Public License 2.0 which | ||
| * accompanies this distribution, and is available at | ||
| * https://www.eclipse.org/legal/epl-2.0/ | ||
| * | ||
| * SPDX-License-Identifier: EPL-2.0 | ||
| **********************************************************************/ | ||
| package org.eclipse.tracecompass.ctf.core.event.types; | ||
|
|
||
| import org.eclipse.jdt.annotation.NonNull; | ||
| import org.eclipse.jdt.annotation.Nullable; | ||
| import org.eclipse.tracecompass.ctf.core.CTFException; | ||
| import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer; | ||
| import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; | ||
|
|
||
| /** | ||
| * A CTF blob class declaration. | ||
| * | ||
| * The declaration of a blob data type that can be used to define sequence of | ||
| * zero or more contiguous bytes with an associated IANA media type | ||
| * | ||
| * @since 5.2 | ||
| * @author Arnaud Fiorini | ||
| */ | ||
| public class DynamicBlobDeclaration extends Declaration { | ||
|
|
||
| private String fLengthName; | ||
| private String fMediaType; | ||
|
|
||
| /** | ||
| * Constructor | ||
| * | ||
| * @param lengthName | ||
| * the length field location | ||
| * @param mediaType | ||
| * the IANA media type | ||
| */ | ||
| public DynamicBlobDeclaration(@Nullable String lengthName, String mediaType) { | ||
| fLengthName = lengthName; | ||
| fMediaType = mediaType; | ||
|
Comment on lines
+41
to
+43
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Guard nullable
Proposed fix+import java.util.Objects;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
@@
- private String fLengthName;
- private String fMediaType;
+ private final `@Nullable` String fLengthName;
+ private final String fMediaType;
@@
public `@NonNull` Definition createDefinition(IDefinitionScope definitionScope, `@NonNull` String fieldName, `@NonNull` BitBuffer input) throws CTFException {
+ if (fLengthName == null || fLengthName.isBlank()) {
+ throw new CTFException("Dynamic blob length field location is missing"); //$NON-NLS-1$
+ }
IDefinition lenDef = null;
@@
- return (fLengthName.equals(otherBlob.fLengthName));
+ return Objects.equals(fLengthName, otherBlob.fLengthName);
}Also applies to: 51-52, 122-123 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| @Override | ||
| public @NonNull Definition createDefinition(IDefinitionScope definitionScope, @NonNull String fieldName, @NonNull BitBuffer input) throws CTFException { | ||
| IDefinition lenDef = null; | ||
|
|
||
| if (definitionScope != null) { | ||
| lenDef = definitionScope.lookupDefinition(fLengthName); | ||
| } | ||
|
|
||
| if (lenDef == null) { | ||
| throw new CTFException("Dynamic blob length field not found"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| if (!(lenDef instanceof IntegerDefinition)) { | ||
| throw new CTFException("Dynamic blob length field not integer"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| IntegerDefinition lengthDefinition = (IntegerDefinition) lenDef; | ||
|
|
||
| if (lengthDefinition.getDeclaration().isSigned()) { | ||
| throw new CTFException("Dynamic blob length must not be signed"); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| long length = lengthDefinition.getValue(); | ||
| if ((length > Integer.MAX_VALUE) || (!input.canRead((int) length))) { | ||
| throw new CTFException("Blob is too large " + length); //$NON-NLS-1$ | ||
| } | ||
|
|
||
| byte[] array = new byte[(int) length]; | ||
| if (input.getByteBuffer().remaining() < length) { | ||
| throw new CTFException("There is not enough data provided. Length asked: " + length + " Remaining buffer size: " + input.getByteBuffer().remaining()); //$NON-NLS-1$ //$NON-NLS-2$ | ||
| } | ||
|
|
||
| /* Offset the buffer position wrt the current alignment */ | ||
| alignRead(input); | ||
| input.get(array); | ||
|
|
||
| return new DynamicBlobDefinition(this, definitionScope, fieldName, array, fMediaType); | ||
| } | ||
|
|
||
| @Override | ||
| public int getMaximumSize() { | ||
| return Integer.MAX_VALUE; | ||
| } | ||
|
|
||
| /** | ||
| * From the documentation: | ||
| * https://diamon.org/ctf/files/CTF2-SPECRC-7.0rA.html#align-dec | ||
| * | ||
| * Alignment of a blob will always be 8 bits | ||
| */ | ||
| @Override | ||
| public long getAlignment() { | ||
| return 8; | ||
| } | ||
|
|
||
| @Override | ||
| public String toString() { | ||
| /* Only used for debugging */ | ||
| return "[declaration] dynamicblob[length-field-location=" + fLengthName + ", media-type=" + fMediaType + ']'; //$NON-NLS-1$ //$NON-NLS-2$ | ||
| } | ||
|
|
||
| @Override | ||
| public boolean isBinaryEquivalent(IDeclaration other) { | ||
| if (this == other) { | ||
| return true; | ||
| } | ||
| if (other == null) { | ||
| return false; | ||
| } | ||
| if (getClass() != other.getClass()) { | ||
| return false; | ||
| } | ||
| DynamicBlobDeclaration otherBlob = (DynamicBlobDeclaration) other; | ||
| if (!fMediaType.equals(otherBlob.fMediaType)) { | ||
| return false; | ||
| } | ||
| return (fLengthName.equals(otherBlob.fLengthName)); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.