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.IMAGE_SYMBOL; 31 import jdk.tools.jaotc.binformat.pecoff.PECoffSymbol; 32 import jdk.tools.jaotc.binformat.pecoff.PECoffByteBuffer; 33 34 final class PECoffSymtab { 35 ArrayList<PECoffSymbol> symbols = new ArrayList<>(); 36 37 /** 38 * number of symbols added 39 */ 40 private int symbolCount; 41 42 /** 43 * String holding symbol table strings 44 */ 45 private final StringBuilder strTabContent; 46 47 /** 48 * Keeps track of bytes in string table since strTabContent.length() is number of chars, not 49 * bytes. 50 */ 51 private int strTabNrOfBytes; 52 53 /** 54 * String holding Linker Directives 55 */ 56 private final StringBuilder directives; 57 58 PECoffSymtab() { 59 symbolCount = 0; 60 strTabContent = new StringBuilder(); 61 directives = new StringBuilder(); 62 63 // The first 4 bytes of the string table contain 64 // the length of the table (including this length field). 65 strTabNrOfBytes = 4; 66 67 // Make room for the 4 byte length field 68 strTabContent.append('\0').append('\0').append('\0').append('\0'); 69 70 // Linker Directives start with 3 spaces to signify ANSI 71 directives.append(" "); 72 } 73 74 PECoffSymbol addSymbolEntry(String name, byte type, byte storageclass, byte secHdrIndex, long offset) { 75 // Get the current symbol index and append symbol name to string table. 76 int index; 77 PECoffSymbol sym; 78 79 if (name.isEmpty()) { 80 index = 0; 81 strTabContent.append('\0'); 82 strTabNrOfBytes += 1; 83 sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset); 84 symbols.add(sym); 85 } else { 86 int nameSize = name.getBytes().length; 87 88 // We can't trust strTabContent.length() since that is 89 // chars (UTF16), keep track of bytes on our own. 90 index = strTabNrOfBytes; 91 // strTabContent.append('_').append(name).append('\0'); 92 strTabContent.append(name).append('\0'); 93 strTabNrOfBytes += (nameSize + 1); 94 95 sym = new PECoffSymbol(symbolCount, index, type, storageclass, secHdrIndex, offset); 96 symbols.add(sym); 97 if (storageclass == IMAGE_SYMBOL.IMAGE_SYM_CLASS_EXTERNAL) { 98 addDirective(name, type); 99 } 100 } 101 symbolCount++; 102 return (sym); 103 } 104 105 private void addDirective(String name, byte type) { 106 directives.append("/EXPORT:" + name); 107 if (type != IMAGE_SYMBOL.IMAGE_SYM_DTYPE_FUNCTION) { 108 directives.append(",DATA"); 109 } 110 directives.append(" "); 111 } 112 113 int getSymtabCount() { 114 return symbolCount; 115 } 116 117 int getStrtabSize() { 118 return strTabNrOfBytes; 119 } 120 121 // Return a byte array that contains the symbol table entries 122 byte[] getSymtabArray() { 123 ByteBuffer symtabData = PECoffByteBuffer.allocate(symbolCount * IMAGE_SYMBOL.totalsize); 124 symtabData.order(ByteOrder.LITTLE_ENDIAN); 125 126 // copy all symbols 127 for (int i = 0; i < symbolCount; i++) { 128 PECoffSymbol sym = symbols.get(i); 129 byte[] arr = sym.getArray(); 130 symtabData.put(arr); 131 } 132 return (symtabData.array()); 133 } 134 135 // Return the string table array 136 byte[] getStrtabArray() { 137 byte[] strs = strTabContent.toString().getBytes(); 138 139 // Update the size of the string table 140 ByteBuffer buff = ByteBuffer.wrap(strs); 141 buff.order(ByteOrder.LITTLE_ENDIAN); 142 buff.putInt(0, strTabNrOfBytes); 143 144 return (strs); 145 } 146 147 byte[] getDirectiveArray() { 148 return (directives.toString().getBytes()); 149 } 150 }