1use std::io::Read;
9
10use crate::error::DexError;
11use crate::adler32;
12use crate::dex::reader::DexReader;
13
14#[derive(Debug)]
16pub struct DexHeader {
17 pub version: [u8; 3],
18 pub checksum: u32,
19 pub signature: [u8; 20],
20 pub file_size: u32,
21 pub header_size: u32,
22 pub endian_tag: u32,
23 pub link_size: u32,
24 pub link_off: u32,
25 pub map_off: u32,
26 pub string_ids_size: u32,
27 pub string_ids_off: u32,
28 pub type_ids_size: u32,
29 pub type_ids_off: u32,
30 pub proto_ids_size: u32,
31 pub proto_ids_off: u32,
32 pub fields_ids_size: u32,
33 pub fields_ids_off: u32,
34 pub method_ids_size: u32,
35 pub method_ids_off: u32,
36 pub class_defs_size: u32,
37 pub class_defs_off: u32,
38 pub data_size: u32,
39 pub data_off: u32
40}
41
42impl DexHeader {
43 pub fn new(dex_cursor: &mut DexReader) -> Result<DexHeader, DexError> {
45 let mut magic = [0; 8];
47 dex_cursor.bytes.read_exact(&mut magic)?;
48 let mut version = [0; 3];
49 version[0] = magic[4];
50 version[1] = magic[5];
51 version[2] = magic[6];
52
53 let checksum = dex_cursor.read_u32()?;
54 adler32::verify_from_bytes(&dex_cursor.bytes, checksum)?;
55
56 let mut signature = [0; 20];
57 dex_cursor.bytes.read_exact(&mut signature)?;
58
59 let file_size = dex_cursor.read_u32()?;
60 let header_size = dex_cursor.read_u32()?;
61 let endian_tag = dex_cursor.read_u32()?;
62
63 let link_size = dex_cursor.read_u32()?;
64 let link_off = dex_cursor.read_u32()?;
65 let map_off = dex_cursor.read_u32()?;
66 let string_ids_size = dex_cursor.read_u32()?;
67 let string_ids_off = dex_cursor.read_u32()?;
68 let type_ids_size = dex_cursor.read_u32()?;
69 let type_ids_off = dex_cursor.read_u32()?;
70 let proto_ids_size = dex_cursor.read_u32()?;
71 let proto_ids_off = dex_cursor.read_u32()?;
72 let fields_ids_size = dex_cursor.read_u32()?;
73 let fields_ids_off = dex_cursor.read_u32()?;
74 let method_ids_size = dex_cursor.read_u32()?;
75 let method_ids_off = dex_cursor.read_u32()?;
76 let class_defs_size = dex_cursor.read_u32()?;
77 let class_defs_off = dex_cursor.read_u32()?;
78 let data_size = dex_cursor.read_u32()?;
79 let data_off = dex_cursor.read_u32()?;
80
81 Ok(DexHeader {
82 version,
83 checksum,
84 signature,
85 file_size,
86 header_size,
87 endian_tag,
88 link_size,
89 link_off,
90 map_off,
91 string_ids_size,
92 string_ids_off,
93 type_ids_size,
94 type_ids_off,
95 proto_ids_size,
96 proto_ids_off,
97 fields_ids_size,
98 fields_ids_off,
99 method_ids_size,
100 method_ids_off,
101 class_defs_size,
102 class_defs_off,
103 data_size,
104 data_off
105 })
106 }
107}
108
109#[cfg(test)]
110mod tests {
111 use super::*;
112
113 const DEX_DATA: [u8; 128] = [
114 0x64, 0x65, 0x78, 0x0a, 0x30, 0x33, 0x35, 0x00,
115 0x81, 0xc4, 0x10, 0x8e, 0x1c, 0xd2, 0x09, 0x16,
116 0x05, 0x09, 0xc2, 0xb6, 0xe6, 0xbf, 0xfb, 0x47,
117 0x1c, 0xda, 0xa3, 0xab, 0xfb, 0x5d, 0xd1, 0x4a,
118 0x10, 0x85, 0x1b, 0x00, 0x70, 0x00, 0x00, 0x00,
119 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x00, 0x34, 0x84, 0x1b, 0x00,
121 0x44, 0x42, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00,
122 0x41, 0x09, 0x00, 0x00, 0x80, 0x09, 0x01, 0x00,
123 0xf6, 0x0d, 0x00, 0x00, 0x84, 0x2e, 0x01, 0x00,
124 0x5d, 0x20, 0x00, 0x00, 0x0c, 0xd6, 0x01, 0x00,
125 0xab, 0x37, 0x00, 0x00, 0xf4, 0xd8, 0x02, 0x00,
126 0xef, 0x05, 0x00, 0x00, 0x4c, 0x96, 0x04, 0x00,
127 0xe4, 0x30, 0x16, 0x00, 0x2c, 0x54, 0x05, 0x00,
128 0xc2, 0x15, 0x12, 0x00, 0xc4, 0x15, 0x12, 0x00,
129 0xf7, 0x15, 0x12, 0x00, 0x36, 0x16, 0x12, 0x00
130 ];
131
132 fn test_build() {
134 let mut dex_reader = DexReader::build(DEX_DATA.to_vec()).unwrap();
135 let dex_header = DexHeader::new(&mut dex_reader).unwrap();
136
137 assert_eq!(dex_header.version, [0x30, 0x33, 0x35]);
138 assert_eq!(dex_header.checksum, 0x8e10c481);
139 assert_eq!(dex_header.signature, [0x1c, 0xd2, 0x09, 0x16,
140 0x05, 0x09, 0xc2, 0xb6,
141 0xe6, 0xbf, 0xfb, 0x47,
142 0x1c, 0xda, 0xa3, 0xab,
143 0xfb, 0x5d, 0xd1, 0x4a]);
144 assert_eq!(dex_header.file_size, 0x001b8510);
145 assert_eq!(dex_header.header_size, 0x00000070);
146 assert_eq!(dex_header.endian_tag, 0x12345678);
147 assert_eq!(dex_header.link_size, 0x00000000);
148 assert_eq!(dex_header.link_off, 0x00000000);
149 assert_eq!(dex_header.map_off, 0x001b8434);
150 assert_eq!(dex_header.string_ids_size, 0x00004244);
151 assert_eq!(dex_header.string_ids_off, 0x00000070);
152 assert_eq!(dex_header.type_ids_size, 0x00000941);
153 assert_eq!(dex_header.type_ids_off, 0x00010980);
154 assert_eq!(dex_header.proto_ids_size, 0x00000df6);
155 assert_eq!(dex_header.proto_ids_off, 0x00012e84);
156 assert_eq!(dex_header.fields_ids_size, 0x0000205d);
157 assert_eq!(dex_header.fields_ids_off, 0x0001d60c);
158 assert_eq!(dex_header.method_ids_size, 0x000037ab);
159 assert_eq!(dex_header.method_ids_off, 0x0002d8f4);
160 assert_eq!(dex_header.class_defs_size, 0x000005ef);
161 assert_eq!(dex_header.class_defs_off, 0x0004964c);
162 assert_eq!(dex_header.data_size, 0x001630e4);
163 assert_eq!(dex_header.data_off, 0x0005542c);
164 }
165}