Skip to content

Commit 92b6658

Browse files
committed
#11 DEX format - parse items
1 parent 6669338 commit 92b6658

File tree

13 files changed

+437
-78
lines changed

13 files changed

+437
-78
lines changed

FormatDEX/src/main/java/org/freeinternals/format/dex/DexFile.java

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
import java.io.File;
1010
import java.io.IOException;
11+
import java.lang.reflect.Constructor;
12+
import java.lang.reflect.InvocationTargetException;
1113
import java.util.Arrays;
1214
import java.util.Collections;
1315
import java.util.List;
@@ -43,6 +45,11 @@
4345
@SuppressWarnings({"java:S100", "java:S116", "java:S1104"})
4446
public class DexFile extends FileFormat {
4547

48+
/**
49+
* The constant NO_INDEX is used to indicate that an index value is absent.
50+
* Embedded in {@link class_def_item} and {@link debug_info_item}
51+
*/
52+
public static final Type_uint NO_INDEX = new Type_uint(0xffffffff);
4653
private static final Logger LOGGER = Logger.getLogger(DexFile.class.getName());
4754

4855
/**
@@ -75,19 +82,18 @@ public class DexFile extends FileFormat {
7582
*/
7683
public final header_item header;
7784
/**
78-
* String identifiers list, or <code>null<code>.
85+
* String identifiers list, or <code>null</code>.
7986
*/
8087
public final string_id_item[] string_ids;
8188
public final type_id_item[] type_ids;
8289
public final proto_id_item[] proto_ids;
8390
public final field_id_item[] field_ids;
8491
public final method_id_item[] method_ids;
8592
public final class_def_item[] class_defs;
86-
// public Dex_ubyte[] data;
8793
/**
8894
* The parsed file components.
8995
*/
90-
public SortedMap<Long, FileComponent> data = new TreeMap<>();
96+
public final SortedMap<Long, FileComponent> data = new TreeMap<>();
9197
public Type_ubyte[] link_data;
9298

9399
/**
@@ -121,7 +127,7 @@ public DexFile(File file) throws IOException, FileFormatException {
121127
BytesTool.skip(parseEndian, DEX_FILE_MAGIC1.size());
122128
BytesTool.skip(parseEndian, DEX_FILE_MAGIC2.size());
123129
BytesTool.skip(parseEndian, Type_uint.LENGTH); // checksum
124-
BytesTool.skip(parseEndian, 20); // signature
130+
BytesTool.skip(parseEndian, 20); // signature
125131
BytesTool.skip(parseEndian, Type_uint.LENGTH); // file_size
126132
BytesTool.skip(parseEndian, Type_uint.LENGTH); // header_size
127133

@@ -144,7 +150,6 @@ public DexFile(File file) throws IOException, FileFormatException {
144150
}
145151

146152
PosDataInputStreamDex stream = new PosDataInputStreamDex(new PosByteArrayInputStream(super.fileByteArray), endian);
147-
148153
SortedMap<Long, Class<?>> todoData = new TreeMap<>();
149154

150155
// Header
@@ -183,6 +188,9 @@ public DexFile(File file) throws IOException, FileFormatException {
183188
this.proto_ids = new proto_id_item[this.header.proto_ids_size.intValue()];
184189
for (int i = 0; i < this.proto_ids.length; i++) {
185190
this.proto_ids[i] = new proto_id_item(stream);
191+
if (this.proto_ids[i].parameters_off.value != 0) {
192+
todoData.put(this.proto_ids[i].parameters_off.value, type_list.class);
193+
}
186194
}
187195
}
188196

@@ -216,16 +224,34 @@ public DexFile(File file) throws IOException, FileFormatException {
216224
this.class_defs = new class_def_item[this.header.class_defs_size.intValue()];
217225
for (int i = 0; i < this.class_defs.length; i++) {
218226
this.class_defs[i] = new class_def_item(stream);
227+
228+
if (this.class_defs[i].interfaces_off.value != 0) {
229+
todoData.put(this.class_defs[i].interfaces_off.value, type_list.class);
230+
}
231+
if (this.class_defs[i].annotations_off.value != 0) {
232+
todoData.put(this.class_defs[i].annotations_off.value, annotations_directory_item.class);
233+
}
234+
if (this.class_defs[i].class_data_off.value != 0) {
235+
todoData.put(this.class_defs[i].class_data_off.value, class_data_item.class);
236+
}
237+
if (this.class_defs[i].class_data_off.value != 0) {
238+
todoData.put(this.class_defs[i].static_values_off.value, encoded_array_item.class);
239+
}
219240
}
220241
}
221242

222243
// data
223244
for (Map.Entry<Long, Class<?>> todoItem : todoData.entrySet()) {
224-
if (todoItem.getValue() == string_data_item.class) {
225-
stream.flyTo(todoItem.getKey().intValue());
226-
this.data.put(todoItem.getKey(), new string_data_item(stream));
245+
// There is only 1 constructor in the item class
246+
Constructor<?> cons = todoItem.getValue().getDeclaredConstructors()[0];
247+
stream.flyTo(todoItem.getKey().intValue());
248+
try {
249+
this.data.put(todoItem.getKey(), (FileComponent) cons.newInstance(stream));
250+
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
251+
String msg = String.format("newInstance failed for data item at 0x%X of type %s", todoItem.getKey(), todoItem.getValue());
252+
LOGGER.severe(msg);
253+
throw new IOException(msg, e);
227254
}
228-
229255
}
230256
}
231257

FormatDEX/src/main/java/org/freeinternals/format/dex/GenerateTreeNodeDexFile.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@ public interface GenerateTreeNodeDexFile {
2020
static final ResourceBundle MESSAGES = ResourceBundle.getBundle(JTreeDexFile.class.getPackageName() + ".MessagesBundle", Locale.ROOT);
2121
static final String FORMAT_STRING_STRING = "%s - %s";
2222

23-
void generateTreeNode(final DefaultMutableTreeNode parentNode, DexFile dexFile);
23+
void generateTreeNode(final DefaultMutableTreeNode parentNode, final DexFile dexFile);
2424

2525
}

FormatDEX/src/main/java/org/freeinternals/format/dex/JTreeDexFile.java

Lines changed: 16 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import javax.swing.Icon;
1414
import javax.swing.tree.DefaultMutableTreeNode;
1515
import org.freeinternals.commonlib.core.FileComponent;
16+
import org.freeinternals.commonlib.ui.GenerateTreeNode;
1617
import org.freeinternals.commonlib.ui.JTreeNodeFileComponent;
1718
import org.freeinternals.commonlib.ui.UITool;
1819

@@ -28,7 +29,6 @@
2829
public class JTreeDexFile implements GenerateTreeNodeDexFile {
2930

3031
private static final Logger LOGGER = Logger.getLogger(JTreeDexFile.class.getName());
31-
private static final String MESSAGE_CLASS_IDX = "class_idx";
3232

3333
JTreeDexFile() {
3434
}
@@ -193,7 +193,7 @@ private void generate_proto_ids(DefaultMutableTreeNode parentNode, DexFile dexFi
193193
DefaultMutableTreeNode itemNode = new DefaultMutableTreeNode(new JTreeNodeFileComponent(
194194
item.getStartPos(),
195195
item.getLength(),
196-
"proto_id_item[" + String.format("%,d", i) + "]"));
196+
String.format("proto_id_item[%,d] : %s", i, item.get_shorty(dexFile))));
197197
item.generateTreeNode(itemNode, dexFile);
198198
node.add(itemNode);
199199
}
@@ -252,8 +252,6 @@ private void generate_class_defs(DefaultMutableTreeNode parentNode, DexFile dexF
252252
}
253253

254254
int size = dexFile.class_defs.length;
255-
DefaultMutableTreeNode nodeTemp;
256-
257255
DefaultMutableTreeNode node = new DefaultMutableTreeNode(new JTreeNodeFileComponent(
258256
dexFile.header.class_defs_off.intValue(),
259257
size * class_def_item.ITEM_SIZE,
@@ -266,31 +264,9 @@ private void generate_class_defs(DefaultMutableTreeNode parentNode, DexFile dexF
266264
DefaultMutableTreeNode itemNode = new DefaultMutableTreeNode(new JTreeNodeFileComponent(
267265
startPos,
268266
item.getLength(),
269-
"class_def_item[" + String.format("%,d", i) + "]"));
267+
String.format("class_def_item[%,d] %s", i, item.get_class_jls(dexFile))));
268+
item.generateTreeNode(itemNode, dexFile);
270269
node.add(itemNode);
271-
272-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, MESSAGE_CLASS_IDX, item.class_idx);
273-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
274-
275-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, "access_flags", item.access_flags);
276-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
277-
278-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, "superclass_idx", item.superclass_idx);
279-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
280-
281-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, "interfaces_off", item.interfaces_off);
282-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
283-
284-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, "source_file_idx", item.source_file_idx);
285-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
286-
287-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, "annotations_off", item.annotations_off);
288-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
289-
290-
nodeTemp = addNode(itemNode, startPos, Type_uint.LENGTH, "class_data_off", item.class_data_off);
291-
startPos = ((JTreeNodeFileComponent) nodeTemp.getUserObject()).getLastPosPlus1();
292-
293-
addNode(itemNode, startPos, Type_uint.LENGTH, "static_values_off", item.static_values_off);
294270
}
295271
}
296272

@@ -302,21 +278,26 @@ private void generate_data(DefaultMutableTreeNode parentNode, DexFile dexFile) {
302278
DefaultMutableTreeNode node = new DefaultMutableTreeNode(new JTreeNodeFileComponent(
303279
dexFile.header.data_off.intValue(),
304280
dexFile.header.data_size.intValue(),
305-
"data"));
281+
String.format("data [%,d]", dexFile.data.size())));
306282
parentNode.add(node);
307283

308284
for (Map.Entry<Long, FileComponent> item : dexFile.data.entrySet()) {
309-
FileComponent fc = item.getValue();
310-
int startPos = fc.getStartPos();
285+
FileComponent comp = item.getValue();
286+
int startPos = comp.getStartPos();
311287

312288
DefaultMutableTreeNode itemNode = new DefaultMutableTreeNode(new JTreeNodeFileComponent(
313289
startPos,
314-
fc.getLength(),
315-
Type_uint.toString(startPos) + " - " + fc.getClass().getSimpleName()));
290+
comp.getLength(),
291+
Type_uint.toString(startPos) + " - " + comp.getClass().getSimpleName()));
316292
node.add(itemNode);
317293

318-
if (fc instanceof string_data_item) {
319-
((string_data_item) fc).generateTreeNode(itemNode);
294+
if (comp instanceof GenerateTreeNode) {
295+
((GenerateTreeNode) comp).generateTreeNode(itemNode);
296+
} else if (comp instanceof GenerateTreeNodeDexFile) {
297+
((GenerateTreeNodeDexFile) comp).generateTreeNode(itemNode, dexFile);
298+
} else {
299+
// This should never happen, or else it is a coding logic error
300+
LOGGER.severe(String.format("FileComponent is not added to the tree: position=0x%X type=%s", comp.getStartPos(), comp.getClass().getName()));
320301
}
321302
}
322303
}

FormatDEX/src/main/java/org/freeinternals/format/dex/Type_uint.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,18 @@ protected Type_uint(long l) {
3535
this.value = l;
3636
}
3737

38+
@Override
39+
public boolean equals(Object other) {
40+
return other instanceof Type_uint && ((Type_uint)other).value == this.value;
41+
}
42+
43+
@Override
44+
public int hashCode() {
45+
return Long.valueOf(this.value).hashCode();
46+
}
47+
3848
public int intValue() {
39-
return (int)value;
49+
return (int) value;
4050
}
4151

4252
@Override
@@ -46,7 +56,7 @@ public String toString() {
4656

4757
/**
4858
* Convert <code>long</code> to String with both offset and readable format.
49-
*
59+
*
5060
* @param l The <code>long</code> value
5161
* @return The String for <code>l</code>
5262
*/

FormatDEX/src/main/java/org/freeinternals/format/dex/annotations_directory_item.java

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77
package org.freeinternals.format.dex;
88

9+
import java.io.IOException;
10+
import javax.swing.tree.DefaultMutableTreeNode;
911
import org.freeinternals.commonlib.core.FileComponent;
1012

1113
/**
@@ -19,6 +21,56 @@
1921
* </pre>
2022
*/
2123
@SuppressWarnings({"java:S101", "java:S116", "java:S1104"})
22-
public class annotations_directory_item extends FileComponent{
23-
24+
public class annotations_directory_item extends FileComponent implements GenerateTreeNodeDexFile{
25+
public final Type_uint class_annotations_off;
26+
public final Type_uint fields_size;
27+
public final Type_uint annotated_methods_size;
28+
public final Type_uint annotated_parameters_size;
29+
public final field_annotation[] field_annotations;
30+
public final method_annotation[] method_annotations;
31+
public final parameter_annotation[] parameter_annotations;
32+
33+
annotations_directory_item(PosDataInputStreamDex stream) throws IOException {
34+
super.startPos = stream.getPos();
35+
this.class_annotations_off = stream.Dex_uint();
36+
this.fields_size = stream.Dex_uint();
37+
this.annotated_methods_size = stream.Dex_uint();
38+
this.annotated_parameters_size = stream.Dex_uint();
39+
40+
// to change
41+
this.field_annotations = null;
42+
this.method_annotations = null;
43+
this.parameter_annotations = null;
44+
45+
super.length = stream.getPos() - super.startPos;
46+
}
47+
48+
@Override
49+
public void generateTreeNode(DefaultMutableTreeNode parentNode, DexFile dexFile) {
50+
// to add
51+
}
52+
53+
public static class field_annotation extends FileComponent implements GenerateTreeNodeDexFile {
54+
55+
@Override
56+
public void generateTreeNode(DefaultMutableTreeNode parentNode, DexFile dexFile) {
57+
// to add
58+
}
59+
}
60+
61+
public static class method_annotation extends FileComponent implements GenerateTreeNodeDexFile {
62+
63+
@Override
64+
public void generateTreeNode(DefaultMutableTreeNode parentNode, DexFile dexFile) {
65+
// to add
66+
}
67+
}
68+
69+
public static class parameter_annotation extends FileComponent implements GenerateTreeNodeDexFile {
70+
71+
@Override
72+
public void generateTreeNode(DefaultMutableTreeNode parentNode, DexFile dexFile) {
73+
// to add
74+
}
75+
}
2476
}

FormatDEX/src/main/java/org/freeinternals/format/dex/class_data_item.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ public class class_data_item extends FileComponent implements GenerateTreeNode {
8989

9090
@Override
9191
public void generateTreeNode(DefaultMutableTreeNode parentNode) {
92-
throw new UnsupportedOperationException("Not supported yet 1.");
92+
// to add
9393
}
9494

9595
public static class encoded_field extends FileComponent implements GenerateTreeNode {

0 commit comments

Comments
 (0)