/* ### * IP: GHIDRA * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ghidra.app.util.bin.format.elf; import java.io.IOException; import ghidra.app.util.bin.BinaryReader; import ghidra.app.util.bin.format.FactoryBundledWithBinaryReader; import ghidra.program.model.data.DataType; import ghidra.util.Msg; import ghidra.util.exception.DuplicateNameException; public class ElfStringTable implements ElfFileSection { /** * Create and parse an Elf string table * @param reader the binary reader containing the elf string table * @param header elf header * @param stringTableSection string table section header or null if associated with a dynamic table entry * @param fileOffset symbol table file offset * @param addrOffset memory address of symbol table (should already be adjusted for prelink) * @param length length of symbol table in bytes of -1 if unknown * @return Elf string table object * @throws IOException */ public static ElfStringTable createElfStringTable(FactoryBundledWithBinaryReader reader, ElfHeader header, ElfSectionHeader stringTableSection, long fileOffset, long addrOffset, long length) throws IOException { ElfStringTable elfStringTable = (ElfStringTable) reader.getFactory().create(ElfStringTable.class); elfStringTable.initElfStringTable(reader, header, stringTableSection, fileOffset, addrOffset, length); return elfStringTable; } private ElfHeader header; private ElfSectionHeader stringTableSection; // may be null private long fileOffset; private long addrOffset; private long length; // private LongObjectHashtable<String> stringOffsetMap; /** * DO NOT USE THIS CONSTRUCTOR, USE create*(GenericFactory ...) FACTORY METHODS INSTEAD. */ public ElfStringTable() { } private void initElfStringTable(FactoryBundledWithBinaryReader reader, ElfHeader header, ElfSectionHeader stringTableSection, long fileOffset, long addrOffset, long length) { this.header = header; this.stringTableSection = stringTableSection; this.fileOffset = fileOffset; this.addrOffset = addrOffset; this.length = length; } /** * Read string from table at specified relative table offset * @param reader * @param stringOffset table relative string offset * @return string or null on error */ public String readString(BinaryReader reader, long stringOffset) { if (fileOffset < 0) { return null; } try { if (stringOffset >= length) { throw new IOException("String read beyond table bounds"); } return reader.readAsciiString(fileOffset + stringOffset); } catch (IOException e) { Msg.error(this, "Failed to read Elf String at offset 0x" + Long.toHexString(stringOffset) + " within String Table at offset 0x" + Long.toHexString(fileOffset)); } return null; } @Override public long getAddressOffset() { return header.adjustAddressForPrelink(addrOffset); } /** * Get section header which corresponds to this table, or null * if only associated with a dynamic table entry * @return string table section header or null */ public ElfSectionHeader getTableSectionHeader() { return stringTableSection; } @Override public long getFileOffset() { return fileOffset; } @Override public long getLength() { return length; } @Override public int getEntrySize() { return -1; } @Override public DataType toDataType() throws DuplicateNameException, IOException { // no uniform structure to be applied return null; } }