/*
 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.tools.jaotc.binformat.elf;

import java.nio.ByteBuffer;
import java.util.ArrayList;

import jdk.tools.jaotc.binformat.elf.Elf.Elf64_Sym;
import jdk.tools.jaotc.binformat.elf.ElfSymbol;
import jdk.tools.jaotc.binformat.elf.ElfByteBuffer;

final class ElfSymtab {

    private final ArrayList<ElfSymbol> localSymbols = new ArrayList<>();
    private final ArrayList<ElfSymbol> globalSymbols = new ArrayList<>();

    
number of symbols added
/** * number of symbols added */
private int symbolCount;
String holding symbol table strings
/** * String holding symbol table strings */
private final StringBuilder strTabContent = new StringBuilder();
Keeps track of bytes in string table since strTabContent.length() is number of chars, not bytes.
/** * Keeps track of bytes in string table since strTabContent.length() is number of chars, not * bytes. */
private int strTabNrOfBytes = 0; ElfSymtab() { symbolCount = 0; } ElfSymbol addSymbolEntry(String name, byte type, byte bind, byte secHdrIndex, long offset, long size) { // Get the current symbol index and append symbol name to string table. int index; ElfSymbol sym; if (name.isEmpty()) { index = 0; strTabContent.append('\0'); strTabNrOfBytes += 1; sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); localSymbols.add(sym); } else { // We can't trust strTabContent.length() since that is // chars (UTF16), keep track of bytes on our own. index = strTabNrOfBytes; // strTabContent.append("_").append(name).append('\0'); strTabContent.append(name).append('\0'); // + 1 for null, + 1 for "_" // strTabNrOfBytes += (name.getBytes().length + 1 + 1); strTabNrOfBytes += (name.getBytes().length + 1); sym = new ElfSymbol(symbolCount, index, type, bind, secHdrIndex, offset, size); if ((bind & Elf64_Sym.STB_GLOBAL) != 0) globalSymbols.add(sym); else localSymbols.add(sym); } symbolCount++; return (sym); } // Update the symbol indexes once all symbols have been added. // This is required since we'll be reordering the symbols in the // file to be in the order of Local then global. void updateIndexes() { int index = 0; // Update the local symbol indexes for (int i = 0; i < localSymbols.size(); i++) { ElfSymbol sym = localSymbols.get(i); sym.setIndex(index++); } // Update the global symbol indexes for (int i = 0; i < globalSymbols.size(); i++) { ElfSymbol sym = globalSymbols.get(i); sym.setIndex(index++); } } int getNumLocalSyms() { return localSymbols.size(); } int getNumGlobalSyms() { return globalSymbols.size(); } // Create a single byte array that contains the symbol table entries byte[] getSymtabArray() { ByteBuffer symtabData = ElfByteBuffer.allocate(symbolCount * Elf64_Sym.totalsize); byte[] retarray; updateIndexes(); // Add the local symbols for (int i = 0; i < localSymbols.size(); i++) { ElfSymbol sym = localSymbols.get(i); byte[] arr = sym.getArray(); symtabData.put(arr); } // Add the global symbols for (int i = 0; i < globalSymbols.size(); i++) { ElfSymbol sym = globalSymbols.get(i); byte[] arr = sym.getArray(); symtabData.put(arr); } retarray = symtabData.array(); return (retarray); } // Return the string table array byte[] getStrtabArray() { byte[] strs = strTabContent.toString().getBytes(); return (strs); } }