View Javadoc

1   // Section.java, created Wed Mar  6 18:38:47 2002 by joewhaley
2   // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Linker.ELF;
5   
6   import java.util.HashMap;
7   import java.util.HashSet;
8   import java.util.Iterator;
9   import java.util.LinkedList;
10  import java.util.List;
11  import java.util.Map;
12  import java.util.Set;
13  import java.util.SortedMap;
14  import java.util.TreeMap;
15  import java.io.IOException;
16  import java.io.UnsupportedEncodingException;
17  import jwutil.collections.AppendIterator;
18  import jwutil.strings.Strings;
19  import jwutil.util.Assert;
20  
21  /***
22   * Defines a section in an ELF file.
23   *
24   * @author  John Whaley <jwhaley@alum.mit.edu>
25   * @version $Id: Section.java 1941 2004-09-30 03:37:06Z joewhaley $
26   */
27  public abstract class Section implements ELFConstants {
28      
29      public static final String DEFAULT_ENCODING = "ISO-8859-1";
30      
31      protected String name;
32      protected int index;
33      protected int flags;
34      protected int addr;
35  
36      public int getIndex() { return index; }
37      public String getName() { return name; }
38      public abstract int getType();
39      public int getFlags() { return flags; }
40      public int getAddr() { return addr; }
41      public abstract int getSize();
42      public abstract int getLink();
43      public abstract int getInfo();
44      public abstract int getAddrAlign();
45      public abstract int getEntSize();
46  
47      public void setIndex(int index) { this.index = index; }
48      public void setName(String name) { this.name = name; }
49      public void setAddr(int addr) { this.addr = addr; }
50      public void setWrite() { this.flags |= SHF_WRITE; }
51      public void clearWrite() { this.flags &= ~SHF_WRITE; }
52      public void setAlloc() { this.flags |= SHF_ALLOC; }
53      public void clearAlloc() { this.flags &= ~SHF_ALLOC; }
54      public void setExecInstr() { this.flags |= SHF_EXECINSTR; }
55      public void clearExecInstr() { this.flags &= ~SHF_EXECINSTR; }
56  
57      public void writeHeader(ELF file, int offset) throws IOException {
58          file.write_sectionname(this.getName());
59          file.write_word(this.getType());
60          file.write_word(this.getFlags());
61          file.write_addr(this.getAddr());
62          file.write_off(offset);
63          file.write_word(this.getSize());
64          file.write_word(this.getLink());
65          file.write_word(this.getInfo());
66          file.write_word(this.getAddrAlign());
67          file.write_word(this.getEntSize());
68      }
69      
70      public abstract void writeData(ELF file) throws IOException;
71      public abstract void load(UnloadedSection s, ELF file) throws IOException;
72      
73      /*** Creates new Section */
74      protected Section(String name, int flags, int addr) {
75          this.name = name; this.flags = flags; this.addr = addr;
76      }
77  
78      protected Section(int flags, int addr) {
79          this.flags = flags; this.addr = addr;
80      }
81      
82      public static class UnloadedSection {
83          
84          int sectionNameIndex;
85          int type;
86          int flags;
87          int addr;
88          int offset;
89          int size;
90          int link;
91          int info;
92          int addralign;
93          int entsize;
94          
95          public UnloadedSection(ELF file) throws IOException {
96              readHeader(file);
97          }
98          
99          public void readHeader(ELF file) throws IOException {
100             this.sectionNameIndex = file.read_word();
101             this.type = file.read_word();
102             this.flags = file.read_word();
103             this.addr = file.read_addr();
104             this.offset = file.read_off();
105             this.size = file.read_word();
106             this.link = file.read_word();
107             this.info = file.read_word();
108             this.addralign = file.read_word();
109             this.entsize = file.read_word();
110         }
111 
112         public Section parseHeader() throws IOException {
113             switch (type) {
114             case SHT_NULL: {
115                 if (this.flags != 0)
116                     System.err.println("Warning! Null section flags is not 0: "+this.flags);
117                 if (this.addr != 0)
118                     System.err.println("Warning! Null section addr is not 0: "+this.addr);
119                 if (this.offset != 0)
120                     System.err.println("Warning! Null section offset is not 0: "+this.offset);
121                 if (this.size != 0)
122                     System.err.println("Warning! Null section size is not 0: "+this.size);
123                 if (this.link != SHN_UNDEF)
124                     System.err.println("Warning! Null section link is not SHN_UNDEF: "+this.link);
125                 if (this.info != 0)
126                     System.err.println("Warning! Null section info is not 0: "+this.info);
127                 if (this.addralign != 0)
128                     System.err.println("Warning! Null section addralign is not 0: "+this.addralign);
129                 if (this.entsize != 0)
130                     System.err.println("Warning! Null section entsize is not 0: "+this.entsize);
131                 return NullSection.INSTANCE;
132             }
133             case SHT_PROGBITS: {
134                 Assert._assert(this.link == SHN_UNDEF);
135                 Assert._assert(this.info == 0);
136                 Assert._assert(this.entsize == 0);
137                 return ProgBitsSectionImpl.empty(this.flags, this.addr, this.addralign);
138             }
139             case SHT_SYMTAB: {
140                 Assert._assert(this.addralign == 4);
141                 Assert._assert(this.entsize == SymbolTableEntry.getEntrySize());
142                 return SymTabSection.empty(this.flags, this.addr);
143             }
144             case SHT_STRTAB: {
145                 if (this.link != SHN_UNDEF)
146                     System.err.println("Warning! Strtab section link is not SHN_UNDEF: "+this.link);
147                 if (this.info != 0)
148                     System.err.println("Warning! Strtab section info is not 0: "+this.info);
149                 if (this.addralign != 1)
150                     System.err.println("Warning! Strtab section addralign is not 0: "+this.addralign);
151                 if (this.entsize != 0)
152                     System.err.println("Warning! Strtab section entsize is not 0: "+this.entsize);
153                 return StrTabSection.empty(this.flags, this.addr);
154             }
155             case SHT_RELA:
156             case SHT_HASH:
157             case SHT_DYNAMIC:
158             case SHT_DYNSYM: {
159                 Assert.TODO(); return null;
160             }
161             case SHT_NOTE: {
162                 if (this.link != SHN_UNDEF)
163                     System.err.println("Warning! Note section link is not SHN_UNDEF: "+this.link);
164                 if (this.info != 0)
165                     System.err.println("Warning! Note section info is not 0: "+this.info);
166                 if (this.addralign != 1)
167                     System.err.println("Warning! Note section addralign is not 0: "+this.addralign);
168                 if (this.entsize != 0)
169                     System.err.println("Warning! Note section entsize is not 0: "+this.entsize);
170                 return NoteSection.empty(this.flags, this.addr);
171             }
172             case SHT_NOBITS: {
173                 if (this.link != SHN_UNDEF)
174                     System.err.println("Warning! Nobits section link is not SHN_UNDEF: "+this.link);
175                 if (this.info != 0)
176                     System.err.println("Warning! Nobits section info is not 0: "+this.info);
177                 if (this.entsize != 0)
178                     System.err.println("Warning! Nobits section entsize is not 0: "+this.entsize);
179                 return NoBitsSection.empty(this.flags, this.addr, this.size, this.addralign);
180             }
181             case SHT_REL:
182                 Assert._assert(this.addralign == 4);
183                 Assert._assert(this.entsize == RelocEntry.getEntrySize());
184                 return RelSection.empty(this.flags, this.addr);
185             case SHT_SHLIB:
186             default:
187                 // unsupported.
188                 throw new IOException("bad section type: "+Strings.hex(type));
189             }
190         }
191         
192     }
193     
194     public abstract static class FakeSection extends Section {
195         
196         FakeSection(String name, int index) { super(name, 0, 0); this.index = index; }
197         public int getEntSize() { Assert.UNREACHABLE(); return 0; }
198         public int getInfo() { Assert.UNREACHABLE(); return 0; }
199         public int getAddrAlign() { Assert.UNREACHABLE(); return 0; }
200         public int getLink() { Assert.UNREACHABLE(); return 0; }
201         public int getSize() { Assert.UNREACHABLE(); return 0; }
202         public int getType() { Assert.UNREACHABLE(); return 0; }
203         public int getFlags() { Assert.UNREACHABLE(); return 0; }
204         public int getAddr() { Assert.UNREACHABLE(); return 0; }
205         public int getIndex() { return index; }
206         public void setName(String name) { Assert.UNREACHABLE(); }
207         public void setAddr(int addr) { Assert.UNREACHABLE(); }
208         public void setWrite() { Assert.UNREACHABLE(); }
209         public void clearWrite() { Assert.UNREACHABLE(); }
210         public void setAlloc() { Assert.UNREACHABLE(); }
211         public void clearAlloc() { Assert.UNREACHABLE(); }
212         public void setExecInstr() { Assert.UNREACHABLE(); }
213         public void clearExecInstr() { Assert.UNREACHABLE(); }
214         public void writeData(ELF file) throws IOException {
215             Assert.UNREACHABLE();
216         }
217         public void load(UnloadedSection s, ELF file) throws IOException {
218             Assert.UNREACHABLE();
219         }
220         
221     }
222     
223     public static class AbsSection extends FakeSection {
224         public static final AbsSection INSTANCE = new AbsSection();
225         private AbsSection() { super("ABS", SHN_ABS); }
226     }
227         
228     public static class NullSection extends Section {
229         public static final NullSection INSTANCE = new NullSection();
230         private NullSection() { super("", 0, 0); }
231         public int getIndex() { return 0; }
232         public int getType() { return SHT_NULL; }
233         public int getSize() { return 0; }
234         public int getLink() { return SHN_UNDEF; }
235         public int getInfo() { return 0; }
236         public int getAddrAlign() { return 0; }
237         public int getEntSize() { return 0; }
238         public void setIndex(int index) { Assert._assert(index == 0); }
239         public void setName(String name) { Assert._assert(name.equals("")); }
240         public void setAddr(int addr) { Assert._assert(addr == 0); }
241         public void setOffset(int offset) { Assert._assert(offset == 0); }
242         public void setWrite() { Assert.UNREACHABLE(); }
243         public void setAlloc() { Assert.UNREACHABLE(); }
244         public void setExecInstr() { Assert.UNREACHABLE(); }
245         public void writeData(ELF file) throws IOException { }
246         public void load(UnloadedSection s, ELF file) throws IOException { }
247     }
248     
249     public abstract static class ProgBitsSection extends Section {
250         public ProgBitsSection(String name, int flags, int addr) {
251             super(name, flags, addr);
252         }
253         protected ProgBitsSection(int flags, int addr) {
254             super(flags, addr);
255         }
256         public final int getType() { return SHT_PROGBITS; }
257         public final int getLink() { return SHN_UNDEF; }
258         public final int getInfo() { return 0; }
259         public final int getEntSize() { return 0; }
260         
261     }
262     
263     public static class ProgBitsSectionImpl extends ProgBitsSection {
264         protected int addralign;
265         protected byte[] data;
266         public ProgBitsSectionImpl(String name, int flags, int addr, int addralign, byte[] data) {
267             super(name, flags, addr);
268             this.addralign = addralign;
269             this.data = data;
270         }
271         protected ProgBitsSectionImpl(int flags, int addr, int addralign) {
272             super(flags, addr);
273             this.addralign = addralign;
274         }
275         public final int getSize() { return data.length; }
276         public final int getAddr() { return addr; }
277         public final int getAddrAlign() { return addralign; }
278         public void writeData(ELF file) throws IOException {
279             file.write_bytes(data);
280         }
281         
282         public static ProgBitsSectionImpl empty(int flags, int addr, int addralign) {
283             return new ProgBitsSectionImpl(flags, addr, addralign);
284         }
285         
286         public void load(UnloadedSection s, ELF file) throws IOException {
287             if (s.sectionNameIndex != 0) {
288                 StrTabSection ss = file.getSectionHeaderStringTable();
289                 if (ss == null) throw new IOException();
290                 this.name = ss.getString(s.sectionNameIndex);
291             }
292             this.data = new byte[s.size];
293             file.set_position(s.offset);
294             file.read_bytes(data);
295         }
296     }
297     
298     public static class SymTabSection extends Section {
299         List/*<SymbolTableEntry>*/ localSymbols, globalSymbols;
300         StrTabSection stringTable;
301         public SymTabSection(String name, int flags, int addr, StrTabSection stringTable) {
302             super(name, flags, addr);
303             this.stringTable = stringTable;
304             this.localSymbols = new LinkedList(); this.globalSymbols = new LinkedList();
305             addSymbol(SymbolTableEntry.EmptySymbolTableEntry.INSTANCE);
306         }
307         protected SymTabSection(int flags, int addr) {
308             super(flags, addr);
309         }
310         public void addSymbol(SymbolTableEntry e) {
311             stringTable.addString(e.getName());
312             if (e.getBind() == SymbolTableEntry.STB_LOCAL) localSymbols.add(e);
313             else globalSymbols.add(e);
314         }
315         public int getSize() { return (localSymbols.size() + globalSymbols.size()) * SymbolTableEntry.getEntrySize(); }
316         public int getAddrAlign() { return 4; }
317         public final int getType() { return SHT_SYMTAB; }
318         public final int getLink() { return stringTable.getIndex(); }
319         public final int getInfo() { return localSymbols.size(); }
320         public final int getEntSize() { return SymbolTableEntry.getEntrySize(); }
321         public void setIndices() {
322             Iterator i = new AppendIterator(localSymbols.iterator(), globalSymbols.iterator());
323             int j=-1;
324             while (i.hasNext()) {
325                 SymbolTableEntry e = (SymbolTableEntry)i.next();
326                 e.setIndex(++j);
327             }
328         }
329         public SymbolTableEntry getSymbolTableEntry(int i) {
330             if (i < localSymbols.size()) return (SymbolTableEntry)localSymbols.get(i);
331             i -= localSymbols.size();
332             return (SymbolTableEntry)globalSymbols.get(i);
333         }
334         public void writeData(ELF file) throws IOException {
335             Iterator i = new AppendIterator(localSymbols.iterator(), globalSymbols.iterator());
336             while (i.hasNext()) {
337                 SymbolTableEntry e = (SymbolTableEntry)i.next();
338                 e.write(file, stringTable);
339             }
340         }
341         
342         public static SymTabSection empty(int flags, int addr) {
343             return new SymTabSection(flags, addr);
344         }
345         
346         public void load(UnloadedSection s, ELF file) throws IOException {
347             if (s.sectionNameIndex != 0) {
348                 StrTabSection ss = file.getSectionHeaderStringTable();
349                 if (ss == null) throw new IOException();
350                 this.name = ss.getString(s.sectionNameIndex);
351             }
352             this.stringTable = (StrTabSection)file.getSection(s.link);
353             file.set_position(s.offset);
354             int n = s.size / this.getEntSize();
355             if (s.size % this.getEntSize() != 0) throw new IOException();
356             this.localSymbols = new LinkedList(); // size is s.info
357             this.globalSymbols = new LinkedList(); // size is n - s.info
358             while (--n >= 0) {
359                 SymbolTableEntry e = SymbolTableEntry.read(file, this.stringTable);
360                 this.addSymbol(e);
361             }
362             if (this.getInfo() != s.info) throw new IOException();
363         }
364 
365     }
366     
367     public static class DynSymSection extends Section {
368         List/*<SymbolTableEntry>*/ localSymbols, globalSymbols;
369         StrTabSection stringTable;
370         public DynSymSection(String name, int flags, int addr, StrTabSection stringTable) {
371             super(name, flags, addr);
372             this.stringTable = stringTable;
373             this.localSymbols = new LinkedList(); this.globalSymbols = new LinkedList();
374         }
375         protected DynSymSection(int flags, int addr) {
376             super(flags, addr);
377         }
378         public void addSymbol(SymbolTableEntry e) {
379             stringTable.addString(e.getName());
380             if (e.getBind() == SymbolTableEntry.STB_LOCAL) localSymbols.add(e);
381             else globalSymbols.add(e);
382         }
383         public int getSize() { return (localSymbols.size() + globalSymbols.size()) * SymbolTableEntry.getEntrySize(); }
384         public int getAddrAlign() { return 4; }
385         public final int getType() { return SHT_DYNSYM; }
386         public final int getLink() { return stringTable.getIndex(); }
387         public final int getInfo() { return localSymbols.size(); }
388         public final int getEntSize() { return SymbolTableEntry.getEntrySize(); }
389         public SymbolTableEntry getSymbolTableEntry(int i) {
390             if (i < localSymbols.size()) return (SymbolTableEntry)localSymbols.get(i);
391             i -= localSymbols.size();
392             return (SymbolTableEntry)globalSymbols.get(i);
393         }
394         public void writeData(ELF file) throws IOException {
395             Iterator i = new AppendIterator(localSymbols.iterator(), globalSymbols.iterator());
396             while (i.hasNext()) {
397                 SymbolTableEntry e = (SymbolTableEntry)i.next();
398                 e.write(file, stringTable);
399             }
400         }
401         
402         public static DynSymSection empty(int flags, int addr) {
403             return new DynSymSection(flags, addr);
404         }
405         
406         public void load(UnloadedSection s, ELF file) throws IOException {
407             if (s.sectionNameIndex != 0) {
408                 StrTabSection ss = file.getSectionHeaderStringTable();
409                 if (ss == null) throw new IOException();
410                 this.name = ss.getString(s.sectionNameIndex);
411             }
412             this.stringTable = (StrTabSection)file.getSection(s.link);
413             file.set_position(s.offset);
414             int n = s.size / this.getEntSize();
415             if (s.size % this.getEntSize() != 0) throw new IOException();
416             this.localSymbols = new LinkedList(); // size is s.info
417             this.globalSymbols = new LinkedList(); // size is n - s.info
418             while (--n >= 0) {
419                 SymbolTableEntry e = SymbolTableEntry.read(file, this.stringTable);
420                 this.addSymbol(e);
421             }
422             if (this.getInfo() != s.info) throw new IOException();
423         }
424         
425     }
426     
427     public static class StrTabSection extends Section {
428         protected Map/*<String, Integer>*/ string_map;
429         protected byte[] table;
430         public StrTabSection(String name, int flags, int addr) {
431             super(name, flags, addr);
432             string_map = new HashMap();
433         }
434         protected StrTabSection(int flags, int addr) {
435             super(flags, addr);
436         }
437         public final int getType() { return SHT_STRTAB; }
438         public final int getLink() { return SHN_UNDEF; }
439         public final int getInfo() { return 0; }
440         public final int getEntSize() { return 0; }
441 
442         public final int getNumberOfEntries() { return string_map.size(); }
443 
444         public void addString(String s) { string_map.put(s, null); }
445 
446         public void super_pack() {
447             // separate into bins by size
448             SortedMap tm = new TreeMap();
449             Iterator i = string_map.keySet().iterator();
450             while (i.hasNext()) {
451                 String s = (String)i.next();
452                 int l = -s.length();
453                 Integer in = new Integer(l);
454                 Set set = (Set)tm.get(in);
455                 if (set == null)
456                     tm.put(in, set = new HashSet());
457                 set.add(s);
458             }
459             // go through bins in reverse-size order.
460             List string_set = new LinkedList();
461             i = tm.entrySet().iterator();
462             int index = 1;
463             while (i.hasNext()) {
464                 Map.Entry e = (Map.Entry)i.next();
465                 int in = -((Integer)e.getKey()).intValue();
466                 if (in == 0) break;
467                 Set set = (Set)e.getValue();
468                 for (Iterator j=set.iterator(); j.hasNext(); ) {
469                     String s1 = (String)j.next();
470                     Assert._assert(s1.length() == in);
471                     int index2;
472                     for (Iterator k=string_set.iterator(); ; ) {
473                         if (!k.hasNext()) {
474                             index2 = index;
475                             index += in + 1;
476                             string_set.add(s1);
477                             break;
478                         }
479                         String s2 = (String)k.next();
480                         if (s2.length() == in) {
481                             index2 = index;
482                             index += in + 1;
483                             string_set.add(s1);
484                             break;
485                         }
486                         if (s2.endsWith(s1)) {
487                             //System.out.println("String \""+s1+"\" shares ending with \""+s2+"\"");
488                             index2 = ((Integer)string_map.get(s2)).intValue();
489                             index2 += s2.length();
490                             index2 -= in;
491                             break;
492                         }
493                     }
494                     string_map.put(s1, new Integer(index2));
495                 }
496             }
497             //if (index == 1) index = 0;
498             table = new byte[index];
499             i = string_map.entrySet().iterator();
500             while (i.hasNext()) {
501                 Map.Entry e = (Map.Entry)i.next();
502                 String s = (String)e.getKey();
503                 if (e.getValue() == null) continue;
504                 index = ((Integer)e.getValue()).intValue();
505                 //System.out.println("Writing "+s.length()+" bytes for \""+s+"\" to table index "+index);
506                 
507                 if (false) {
508                     // deprecated
509                     //s.getBytes(0, s.length(), table, index);
510                 } else {
511                     try {
512                         byte[] b = s.getBytes(DEFAULT_ENCODING);
513                         System.arraycopy(b, 0, table, index, b.length);
514                     } catch (UnsupportedEncodingException x) { Assert.UNREACHABLE(); }
515                 }
516             }
517         }
518         
519         public void pack() {
520             int size = 1;
521             Iterator i = string_map.entrySet().iterator();
522             while (i.hasNext()) {
523                 Map.Entry e = (Map.Entry)i.next();
524                 String s = (String)e.getKey();
525                 if (s.length() == 0) {
526                     e.setValue(new Integer(0));
527                 } else {
528                     e.setValue(new Integer(size));
529                     size += s.length() + 1;
530                 }
531             }
532             if (size == 1) size = 0;
533             // todo: combine strings that have the same endings.
534             table = new byte[size];
535             int index = 1;
536             i = string_map.entrySet().iterator();
537             while (i.hasNext()) {
538                 Map.Entry e = (Map.Entry)i.next();
539                 String s = (String)e.getKey();
540                 if (s.length() == 0) {
541                     Assert._assert(((Integer)e.getValue()).intValue() == 0);
542                     continue;
543                 }
544                 //System.out.println("Writing "+s.length()+" bytes for \""+s+"\" to table index "+index);
545                 
546                 if (false) {
547                     // deprecated
548                     //s.getBytes(0, s.length(), table, index);
549                 } else {
550                     try {
551                         byte[] b = s.getBytes(DEFAULT_ENCODING);
552                         Assert._assert(b.length == s.length(), s);
553                         System.arraycopy(b, 0, table, index, b.length);
554                     } catch (UnsupportedEncodingException x) { Assert.UNREACHABLE(); }
555                 }
556                 Assert._assert(((Integer)e.getValue()).intValue() == index, s);
557                 index += s.length() + 1;
558             }
559             Assert._assert(size == 0 || size == index);
560         }
561         
562         public int getStringIndex(String s) {
563             Integer i = (Integer)string_map.get(s);
564             if (i == null)
565                 return 0;
566             Assert._assert(getString(i.intValue()).equals(s), s);
567             return i.intValue();
568         }
569         public String getString(int i) {
570             int n=0;
571             for (;;) {
572                 if (table[n+i] == '\0') break;
573                 ++n;
574             }
575             try {
576                 return new String(table, i, n, DEFAULT_ENCODING);
577             } catch (UnsupportedEncodingException x) { Assert.UNREACHABLE(); return null; }
578         }
579         public int getSize() { return table.length; }
580         public int getAddrAlign() { return 1; }
581         public void writeData(ELF file) throws IOException {
582             file.write_bytes(table);
583         }
584         
585         public static StrTabSection empty(int flags, int addr) {
586             return new StrTabSection(flags, addr);
587         }
588         
589         public void load(UnloadedSection s, ELF file) throws IOException {
590             this.table = new byte[s.size];
591             file.set_position(s.offset);
592             file.read_bytes(this.table);
593             if (s.sectionNameIndex != 0) {
594                 StrTabSection ss = file.getSectionHeaderStringTable();
595                 if (ss == null) throw new IOException();
596                 this.name = ss.getString(s.sectionNameIndex);
597             }
598         }
599     }
600     
601     public static class RelASection extends Section {
602         protected List/*<RelocAEntry>*/ relocs;
603         protected SymTabSection symbolTable;
604         protected Section targetSection;
605         public RelASection(String name, int flags, int addr, SymTabSection symbolTable, Section targetSection) {
606             super(name, flags, addr);
607             this.symbolTable = symbolTable; this.targetSection = targetSection;
608             this.relocs = new LinkedList();
609         }
610         protected RelASection(int flags, int addr) {
611             super(flags, addr);
612         }
613         public final int getType() { return SHT_RELA; }
614         public final int getLink() { return symbolTable.getIndex(); }
615         public final int getInfo() { return targetSection.getIndex(); }
616         public final int getEntSize() { return RelocAEntry.getEntrySize(); }
617         public int getSize() { return relocs.size() * RelocAEntry.getEntrySize(); }
618         public int getAddrAlign() { return 4; }
619         public void addReloc(RelocAEntry e) { relocs.add(e); }
620         public void writeData(ELF file) throws IOException {
621             Iterator i = relocs.iterator();
622             while (i.hasNext()) {
623                 RelocAEntry e = (RelocAEntry)i.next();
624                 e.write(file);
625             }
626         }
627         
628         public static RelASection empty(int flags, int addr) {
629             return new RelASection(flags, addr);
630         }
631         
632         public void load(UnloadedSection s, ELF file) throws IOException {
633             if (s.sectionNameIndex != 0) {
634                 StrTabSection ss = file.getSectionHeaderStringTable();
635                 if (ss == null) throw new IOException();
636                 this.name = ss.getString(s.sectionNameIndex);
637             }
638             this.symbolTable = (SymTabSection)file.getSection(s.link);
639             this.targetSection = file.getSection(s.info);
640             int n = s.size / getEntSize();
641             if (n % getEntSize() != 0) throw new IOException();
642             this.relocs = new LinkedList(); // size = n
643             file.set_position(s.offset);
644             while (--n >= 0) {
645                 RelocAEntry e = (RelocAEntry)RelocAEntry.read(file, this.symbolTable);
646                 this.addReloc(e);
647             }
648         }
649         
650     }
651     
652     public static class HashSection extends Section {
653         protected int sectionIndex;
654         public HashSection(String name, int flags, int addr, int sectionIndex) {
655             super(name, flags, addr);
656             this.sectionIndex = sectionIndex;
657         }
658         public final int getType() { return SHT_HASH; }
659         public final int getLink() { return sectionIndex; }
660         public final int getInfo() { return 0; }
661         public final int getEntSize() { return 0; }
662         public int getSize() { return 0; } // WRITE ME
663         public int getAddrAlign() { return 0; }
664         public void writeData(ELF file) throws IOException {
665             // WRITE ME
666         }
667         public void load(UnloadedSection s, ELF file) throws IOException {
668             // WRITE ME
669         }
670         
671     }
672     
673     public static class DynamicSection extends Section {
674         protected int stringTableIndex;
675         public DynamicSection(String name, int flags, int addr, int stringTableIndex) {
676             super(name, flags, addr);
677             this.stringTableIndex = stringTableIndex;
678         }
679         public final int getType() { return SHT_DYNAMIC; }
680         public final int getLink() { return stringTableIndex; }
681         public final int getInfo() { return 0; }
682         public final int getEntSize() { return 0; }
683         public int getSize() { return 0; } // WRITE ME
684         public int getAddrAlign() { return 0; }
685         public void writeData(ELF file) throws IOException {
686             // WRITE ME
687         }
688         
689         public void load(UnloadedSection s, ELF file) throws IOException {
690         }
691         
692     }
693     
694     public static class NoteSection extends Section {
695         protected String notename;
696         protected byte[] notedesc;
697         protected int notetype;
698         public NoteSection(String sectionname, int flags, int addr, String notename, byte[] notedesc, int notetype) {
699             super(sectionname, flags, addr);
700             this.notename = notename; this.notedesc = notedesc; this.notetype = notetype;
701         }
702         protected NoteSection(int flags, int addr) {
703             super(flags, addr);
704         }
705         public final int getType() { return SHT_NOTE; }
706         public final int getLink() { return SHN_UNDEF; }
707         public final int getInfo() { return 0; }
708         public final int getEntSize() { return 0; }
709         protected int getNameLength() { return (notename.length()+4)&~3; }
710         public int getSize() { return 12 + getNameLength() + notedesc.length; }
711         public int getAddrAlign() { return 1; }
712         public void writeData(ELF file) throws IOException {
713             file.write_word(getNameLength());
714             file.write_word(notedesc.length);
715             file.write_word(notetype);
716             byte[] notename_b = new byte[getNameLength()];
717             if (false) {
718                 // deprecated
719                 //notename.getBytes(0, notename.length(), notename_b, 0);
720             } else {
721                 try {
722                     byte[] b = notename.getBytes(DEFAULT_ENCODING);
723                     System.arraycopy(b, 0, notename_b, 0, b.length);
724                 } catch (UnsupportedEncodingException x) { Assert.UNREACHABLE(); }
725             }
726             file.write_bytes(notename_b);
727             file.write_bytes(notedesc);
728         }
729         
730         public static NoteSection empty(int flags, int addr) {
731             return new NoteSection(flags, addr);
732         }
733         
734         public void load(UnloadedSection s, ELF file) throws IOException {
735             if (s.sectionNameIndex != 0) {
736                 StrTabSection ss = file.getSectionHeaderStringTable();
737                 if (ss == null) throw new IOException();
738                 this.name = ss.getString(s.sectionNameIndex);
739             }
740             file.set_position(s.offset);
741             int nlength = file.read_word();
742             int dlength = file.read_word();
743             this.notetype = file.read_word();
744             byte[] notename_b = new byte[nlength];
745             file.read_bytes(notename_b);
746             try {
747                 this.notename = new String(notename_b, DEFAULT_ENCODING);
748             } catch (UnsupportedEncodingException x) { Assert.UNREACHABLE(); }
749             this.notedesc = new byte[dlength];
750             file.read_bytes(notedesc);
751             if (this.getSize() != s.size) throw new IOException();
752         }
753     }
754     
755     public static class NoBitsSection extends Section {
756         protected int size; protected int addralign;
757         public NoBitsSection(String name, int flags, int addr, int size, int addralign) {
758             super(name, flags, addr);
759             this.size = size; this.addralign = addralign;
760         }
761         protected NoBitsSection(int flags, int addr, int size, int addralign) {
762             super(flags, addr);
763             this.size = size; this.addralign = addralign;
764         }
765         public final int getType() { return SHT_NOBITS; }
766         public final int getLink() { return SHN_UNDEF; }
767         public final int getInfo() { return 0; }
768         public final int getEntSize() { return 0; }
769         public int getSize() { return size; }
770         public int getAddrAlign() { return addralign; }
771         public void writeData(ELF file) throws IOException { }
772         
773         public static NoBitsSection empty(int flags, int addr, int size, int addralign) {
774             return new NoBitsSection(flags, addr, size, addralign);
775         }
776         
777         public void load(UnloadedSection s, ELF file) throws IOException {
778             if (s.sectionNameIndex != 0) {
779                 StrTabSection ss = file.getSectionHeaderStringTable();
780                 if (ss == null) throw new IOException();
781                 this.name = ss.getString(s.sectionNameIndex);
782             }
783         }
784     }
785     
786     public static class RelSection extends Section {
787         protected List/*<RelocEntry>*/ relocs;
788         protected SymTabSection symbolTable;
789         protected Section targetSection;
790         public RelSection(String name, int flags, int addr, SymTabSection symbolTable, Section targetSection) {
791             super(name, flags, addr);
792             this.symbolTable = symbolTable; this.targetSection = targetSection;
793             this.relocs = new LinkedList();
794         }
795         protected RelSection(int flags, int addr) {
796             super(flags, addr);
797         }
798         public final int getType() { return SHT_REL; }
799         public final int getLink() { return symbolTable.getIndex(); }
800         public final int getInfo() { return targetSection.getIndex(); }
801         public final int getEntSize() { return RelocEntry.getEntrySize(); }
802         public int getSize() { return relocs.size() * RelocEntry.getEntrySize(); }
803         public int getAddrAlign() { return 4; }
804         public void addReloc(RelocEntry e) { relocs.add(e); }
805         public void writeData(ELF file) throws IOException {
806             Iterator i = relocs.iterator();
807             while (i.hasNext()) {
808                 RelocEntry e = (RelocEntry)i.next();
809                 e.write(file);
810             }
811         }
812         
813         public static RelSection empty(int flags, int addr) {
814             return new RelSection(flags, addr);
815         }
816         
817         public void load(UnloadedSection s, ELF file) throws IOException {
818             if (s.sectionNameIndex != 0) {
819                 StrTabSection ss = file.getSectionHeaderStringTable();
820                 if (ss == null) throw new IOException();
821                 this.name = ss.getString(s.sectionNameIndex);
822             }
823             this.symbolTable = (SymTabSection)file.getSection(s.link);
824             this.targetSection = file.getSection(s.info);
825             int n = s.size / getEntSize();
826             if (n % getEntSize() != 0) throw new IOException();
827             this.relocs = new LinkedList(); // size = n
828             file.set_position(s.offset);
829             while (--n >= 0) {
830                 RelocEntry e = RelocEntry.read(file, this.symbolTable);
831                 this.addReloc(e);
832             }
833         }
834     }
835     
836     public static int getHeaderSize() { return 40; }
837 }