]> sigrok.org Git - sigrok-androidutils.git/blob - ant/src/org/sigrok/androidutils/ant/ElfFile.java
Add some missing license headers.
[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))
101                 : l);
102     }
103
104     protected short getHalf() throws IOException
105     {
106         return swap(file.readShort());
107     }
108
109     protected int getWord() throws IOException
110     {
111         return swap(file.readInt());
112     }
113
114     protected long getXword() throws IOException
115     {
116         return swap(file.readLong());
117     }
118
119     protected long getAddr() throws IOException
120     {
121         return (bit64? getXword() : getWord());
122     }
123
124     protected long getOff() throws IOException
125     {
126         return (bit64? getXword() : getWord());
127     }
128
129     public class Header
130     {
131         public final byte[] e_ident;
132         public final short e_type, e_machine;
133         public final int e_version;
134         public final long e_entry, e_phoff, e_shoff;
135         public final int e_flags;
136         public final short e_ehsize, e_phentsize, e_phnum;
137         public final short e_shentsize, e_shnum, e_shstrndx;
138
139         private Header(byte[] ident) throws IOException
140         {
141             e_ident = ident;
142             e_type = getHalf();
143             e_machine = getHalf();
144             e_version = getWord();
145             e_entry = getAddr();
146             e_phoff = getOff();
147             e_shoff = getOff();
148             e_flags = getWord();
149             e_ehsize = getHalf();
150             e_phentsize = getHalf();
151             e_phnum = getHalf();
152             e_shentsize = getHalf();
153             e_shnum = getHalf();
154             e_shstrndx = getHalf();
155         }
156     }
157
158     public class SectionHeader
159     {
160         public final int sh_name, sh_type;
161         public final long sh_flags, sh_addr, sh_offset, sh_size;
162         public final int sh_link, sh_info;
163         public final long sh_addralign, sh_entsize;
164
165         private SectionHeader() throws IOException
166         {
167             sh_name = getWord();
168             sh_type = getWord();
169             sh_flags = (bit64? getXword() : getWord());
170             sh_addr = getAddr();
171             sh_offset = getOff();
172             sh_size = (bit64? getXword() : getWord());
173             sh_link = getWord();
174             sh_info = getWord();
175             if (bit64) {
176                 sh_addralign = getXword();
177                 sh_entsize = getXword();
178             } else {
179                 sh_addralign = getWord();
180                 sh_entsize = getWord();
181             }
182         }
183     }
184
185     public class Dynamic
186     {
187         public final long d_tag, d_val;
188
189         private Dynamic() throws IOException
190         {
191             if (bit64) {
192                 d_tag = getXword();
193                 d_val = getXword();
194             } else {
195                 d_tag = getWord();
196                 d_val = getWord();
197             }
198         }
199     }
200
201     public Dynamic[] readDynamic(SectionHeader sh) throws IOException
202     {
203         file.seek(sh.sh_offset);
204         Dynamic[] dyn = new Dynamic[(int)(sh.sh_size/sh.sh_entsize)];
205         for (int i=0; i<dyn.length; i++)
206             dyn[i] = new Dynamic();
207         return dyn;
208     }
209
210     public void read(SectionHeader sh, byte[] buf) throws Exception
211     {
212         if (sh.sh_type == SHT_NOBITS || buf.length > sh.sh_size)
213             throw new Exception("Illegal read");
214         file.seek(sh.sh_offset);
215         file.readFully(buf);
216     }
217
218     public ElfFile(File f) throws Exception
219     {
220         file = new RandomAccessFile(f, "r");
221         file.seek(0);
222         byte[] ident = new byte[16];
223         file.readFully(ident);
224         if (ident[0] != 0x7f || ident[1] != 'E' ||
225             ident[2] != 'L' || ident[3] != 'F')
226             throw new Exception("ELF signature not found");
227         if (ident[4] == 1)
228             bit64 = false;
229         else if (ident[4] == 2)
230             bit64 = true;
231         else
232             throw new Exception("Invalid ELF file class");
233         if (ident[5] == 1)
234             little = true;
235         else if (ident[5] == 2)
236             little = false;
237         else
238             throw new Exception("Invalid ELF data encoding");
239         header = new Header(ident);
240         file.seek(header.e_shoff);
241         secHeaders = new SectionHeader[header.e_shnum];
242         for (int i=0; i<header.e_shnum; i++)
243             secHeaders[i] = new SectionHeader();
244     }
245 }