1 /* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 package jdk.tools.jaotc.binformat.pecoff; 25 26 import java.nio.ByteBuffer; 27 import java.nio.ByteOrder; 28 import java.util.ArrayList; 29 30 import jdk.tools.jaotc.binformat.pecoff.PECoff; 31 import jdk.tools.jaotc.binformat.pecoff.PECoff.IMAGE_SYMBOL; 32 import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; 33 import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; 34 35 public class PECoffSymtab { 36 ArrayList<PECoffSymbol>symbols = new ArrayList<PECoffSymbol>(); 37 38 /** 39 * number of symbols added 40 */ 41 int symbolCount; 42 43 /** 44 * String holding symbol table strings 45 */ 46 private StringBuilder strTabContent; 47 48 /** 49 * Keeps track of bytes in string table since strTabContent.length() 50 * is number of chars, not bytes. 51 */ 52 private int strTabNrOfBytes; 53 54 /** 55 * String holding Linker Directives 56 */ 57 private StringBuilder directives; 58 59 public PECoffSymtab() { 60 symbolCount = 0; 61 strTabContent = new StringBuilder(); 62 directives = new StringBuilder(); 63 64 // The first 4 bytes of the string table contain 65 // the length of the table (including this length field). 66 strTabNrOfBytes = 4; 67 68 // Make room for the 4 byte length field 69 strTabContent.append('\0').append('\0').append('\0').append('\0'); 70 71 // Linker Directives start with 3 spaces to signify ANSI 72 directives.append(" "); 73 } 74 75 public PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, 76 byte secHdrIndex, long offset, long size) { 77 // Get the current symbol index and append symbol name to string table. 78 int index; 79 PECoffSymbol sym; 80 81 if (name.isEmpty()) { 82 index = 0; 83 strTabContent.append('\0'); 84 strTabNrOfBytes += 1; 85 sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); 86 symbols.add(sym); 87 } else { 88 int nameSize = name.getBytes().length; 89 90 // We can't trust strTabContent.length() since that is 91 // chars (UTF16), keep track of bytes on our own. 92 index = strTabNrOfBytes; 93 // strTabContent.append('_').append(name).append('\0'); 94 strTabContent.append(name).append('\0'); 95 strTabNrOfBytes += (nameSize + 1); 96 97 sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset, size); 98 symbols.add(sym); 99 if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) 100 addDirective(name, type); 101 } 102 symbolCount++; 103 return (sym); 104 } 105 106 private void addDirective(String name, byte type) { 107 directives.append("/EXPORT:" + name); 108 if(type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) { 109 directives.append(",DATA"); 110 } 111 directives.append(" "); 112 } 113 114 public int getSymtabCount() { 115 return symbolCount; 116 } 117 118 public int getStrtabSize() { 119 return strTabNrOfBytes; 120 } 121 122 // Return a byte array that contains the symbol table entries 123 public byte[] getSymtabArray() { 124 ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount*IMAGE_SYMBOL.totalsize); 125 symtabData.order(ByteOrder.LITTLE_ENDIAN); 126 127 // copy all symbols 128 for (int i = 0; i < symbolCount; i++ ) { 129 PECoffSymbol sym = symbols.get(i); 130 byte [] arr = sym.getArray(); 131 symtabData.put(arr); 132 } 133 return (symtabData.array()); 134 } 135 136 // Return the string table array 137 public byte[] getStrtabArray() { 138 byte [] strs = strTabContent.toString().getBytes(); 139 140 // Update the size of the string table 141 ByteBuffer buff = ByteBuffer.wrap(strs); 142 buff.order(ByteOrder.LITTLE_ENDIAN); 143 buff.putInt(0, strTabNrOfBytes); 144 145 return (strs); 146 } 147 148 public byte[] getDirectiveArray() { 149 return (directives.toString().getBytes()); 150 } 151 }