]> sigrok.org Git - sigrok-androidutils.git/blob - ant/src/org/sigrok/androidutils/ant/ElfFile.java
device_filter.xml: Update.
[sigrok-androidutils.git] / ant / src / org / sigrok / androidutils / ant / ElfFile.java
1 /*
2  * This file is part of the sigrok-androidutils project.
3  *
4  * Copyright (C) 2014 Marcus Comstedt <marcus@mc.pp.se>
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 package org.sigrok.androidutils.ant;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.io.RandomAccessFile;
25
26 class ElfFile
27 {
28         public static final int SHT_NULL = 0;
29         public static final int SHT_PROGBITS = 1;
30         public static final int SHT_SYMTAB = 2;
31         public static final int SHT_STRTAB = 3;
32         public static final int SHT_RELA = 4;
33         public static final int SHT_HASH = 5;
34         public static final int SHT_DYNAMIC = 6;
35         public static final int SHT_NOTE = 7;
36         public static final int SHT_NOBITS = 8;
37         public static final int SHT_REL = 9;
38         public static final int SHT_SHLIB = 10;
39         public static final int SHT_DYNSYM = 11;
40         public static final int SHT_INIT_ARRAY = 14;
41         public static final int SHT_FINI_ARRAY = 15;
42         public static final int SHT_PREINIT_ARRAY = 16;
43         public static final int SHT_GROUP = 17;
44         public static final int SHT_SYMTAB_SHNDX = 18;
45
46         public static final int DT_NULL = 0;
47         public static final int DT_NEEDED = 1;
48         public static final int DT_PLTRELSZ = 2;
49         public static final int DT_PLTGOT = 3;
50         public static final int DT_HASH = 4;
51         public static final int DT_STRTAB = 5;
52         public static final int DT_SYMTAB = 6;
53         public static final int DT_RELA = 7;
54         public static final int DT_RELASZ = 8;
55         public static final int DT_RELAENT = 9;
56         public static final int DT_STRSZ = 10;
57         public static final int DT_SYMENT = 11;
58         public static final int DT_INIT = 12;
59         public static final int DT_FINI = 13;
60         public static final int DT_SONAME = 14;
61         public static final int DT_RPATH = 15;
62         public static final int DT_SYMBOLIC = 16;
63         public static final int DT_REL = 17;
64         public static final int DT_RELSZ = 18;
65         public static final int DT_RELENT = 19;
66         public static final int DT_PLTREL = 20;
67         public static final int DT_DEBUG = 21;
68         public static final int DT_TEXTREL = 22;
69         public static final int DT_JMPREL = 23;
70         public static final int DT_BIND_NOW = 24;
71         public static final int DT_INIT_ARRAY = 25;
72         public static final int DT_FINI_ARRAY = 26;
73         public static final int DT_INIT_ARRAYSZ = 27;
74         public static final int DT_FINI_ARRAYSZ = 28;
75         public static final int DT_RUNPATH = 29;
76         public static final int DT_FLAGS = 30;
77         public static final int DT_ENCODING = 32;
78         public static final int DT_PREINIT_ARRAY = 32;
79         public static final int DT_PREINIT_ARRAYSZ = 33;
80
81         protected final RandomAccessFile file;
82         protected final boolean bit64, little;
83         public final Header header;
84         public final SectionHeader[] secHeaders;
85
86         protected short swap(short s)
87         {
88                 return (little ? (short)(((s & 0xff) << 8) | ((s >> 8) & 0xff)) : s);
89         }
90
91         protected int swap(int i)
92         {
93                 return (little ? (((i & 0xff) << 24) | ((i & 0xff00) << 8) |
94                                 ((i >> 8) & 0xff00) | ((i >> 24) & 0xff)) : i);
95         }
96
97         protected long swap(long l)
98         {
99                 return (little? ((((long)swap((int)(l & 0xffffffffL))) << 32) |
100                                 (((long)swap((int)((l >> 32) & 0xffffffffL))) & 0xffffffffL)) : l);
101         }
102
103         protected short getHalf() throws IOException
104         {
105                 return swap(file.readShort());
106         }
107
108         protected int getWord() throws IOException
109         {
110                 return swap(file.readInt());
111         }
112
113         protected long getXword() throws IOException
114         {
115                 return swap(file.readLong());
116         }
117
118         protected long getAddr() throws IOException
119         {
120                 return (bit64? getXword() : getWord());
121         }
122
123         protected long getOff() throws IOException
124         {
125                 return (bit64 ? getXword() : getWord());
126         }
127
128         public class Header
129         {
130                 public final byte[] e_ident;
131                 public final short e_type, e_machine;
132                 public final int e_version;
133                 public final long e_entry, e_phoff, e_shoff;
134                 public final int e_flags;
135                 public final short e_ehsize, e_phentsize, e_phnum;
136                 public final short e_shentsize, e_shnum, e_shstrndx;
137
138                 private Header(byte[] ident) throws IOException
139                 {
140                         e_ident = ident;
141                         e_type = getHalf();
142                         e_machine = getHalf();
143                         e_version = getWord();
144                         e_entry = getAddr();
145                         e_phoff = getOff();
146                         e_shoff = getOff();
147                         e_flags = getWord();
148                         e_ehsize = getHalf();
149                         e_phentsize = getHalf();
150                         e_phnum = getHalf();
151                         e_shentsize = getHalf();
152                         e_shnum = getHalf();
153                         e_shstrndx = getHalf();
154                 }
155         }
156
157         public class SectionHeader
158         {
159                 public final int sh_name, sh_type;
160                 public final long sh_flags, sh_addr, sh_offset, sh_size;
161                 public final int sh_link, sh_info;
162                 public final long sh_addralign, sh_entsize;
163
164                 private SectionHeader() throws IOException
165                 {
166                         sh_name = getWord();
167                         sh_type = getWord();
168                         sh_flags = (bit64 ? getXword() : getWord());
169                         sh_addr = getAddr();
170                         sh_offset = getOff();
171                         sh_size = (bit64 ? getXword() : getWord());
172                         sh_link = getWord();
173                         sh_info = getWord();
174                         if (bit64) {
175                                 sh_addralign = getXword();
176                                 sh_entsize = getXword();
177                         } else {
178                                 sh_addralign = getWord();
179                                 sh_entsize = getWord();
180                         }
181                 }
182         }
183
184         public class Dynamic
185         {
186                 public final long d_tag, d_val;
187
188                 private Dynamic() throws IOException
189                 {
190                         if (bit64) {
191                                 d_tag = getXword();
192                                 d_val = getXword();
193                         } else {
194                                 d_tag = getWord();
195                                 d_val = getWord();
196                         }
197                 }
198         }
199
200         public Dynamic[] readDynamic(SectionHeader sh) throws IOException
201         {
202                 file.seek(sh.sh_offset);
203                 Dynamic[] dyn = new Dynamic[(int)(sh.sh_size / sh.sh_entsize)];
204                 for (int i = 0; i < dyn.length; i++)
205                         dyn[i] = new Dynamic();
206                 return dyn;
207         }
208
209         public void read(SectionHeader sh, byte[] buf) throws Exception
210         {
211                 if (sh.sh_type == SHT_NOBITS || buf.length > sh.sh_size)
212                         throw new Exception("Illegal read");
213                 file.seek(sh.sh_offset);
214                 file.readFully(buf);
215         }
216
217         public ElfFile(File f) throws Exception
218         {
219                 file = new RandomAccessFile(f, "r");
220                 file.seek(0);
221                 byte[] ident = new byte[16];
222                 file.readFully(ident);
223                 if (ident[0] != 0x7f || ident[1] != 'E' ||
224                         ident[2] != 'L' || ident[3] != 'F')
225                         throw new Exception("ELF signature not found");
226                 if (ident[4] == 1)
227                         bit64 = false;
228                 else if (ident[4] == 2)
229                         bit64 = true;
230                 else
231                         throw new Exception("Invalid ELF file class");
232                 if (ident[5] == 1)
233                         little = true;
234                 else if (ident[5] == 2)
235                         little = false;
236                 else
237                         throw new Exception("Invalid ELF data encoding");
238                 header = new Header(ident);
239                 file.seek(header.e_shoff);
240                 secHeaders = new SectionHeader[header.e_shnum];
241                 for (int i = 0; i < header.e_shnum; i++)
242                         secHeaders[i] = new SectionHeader();
243         }
244 }