All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.fornwall.jelf.ElfGnuHashTable Maven / Gradle / Ivy

There is a newer version: 0.9.8
Show newest version
package net.fornwall.jelf;

import java.io.IOException;

class ElfGnuHashTable implements HashTable {

    private interface HashChain {
        int chain(int index);
    }

    private final int nbucket;
    private final int maskwords;
    private final int shift2;

    private long[] bloom_filters;
    private int[] buckets;
    private HashChain chains;

    private final int bloom_mask_bits;

    ElfGnuHashTable(final ElfParser parser, long offset) {
        parser.seek(offset);
        nbucket = parser.readInt();
        int symndx = parser.readInt();
        int gnu_maskwords_ = parser.readInt();
        shift2 = parser.readInt();

        bloom_filters = new long[gnu_maskwords_];
        for (int i = 0; i < bloom_filters.length; i++) {
            bloom_filters[i] = parser.readIntOrLong();
        }

        buckets = new int[nbucket];
        for (int i = 0; i < nbucket; i++) {
            buckets[i] = parser.readInt();
        }

        final long chain_base = offset + 16 + gnu_maskwords_ * (parser.elfFile.objectSize == ElfFile.CLASS_32 ? 4 : 8) + nbucket * 4 - symndx * 4;
        chains = new HashChain() {
            @Override
            public int chain(int index) {
                parser.seek(chain_base + index * 4);
                return parser.readInt();
            }
        };

        maskwords = gnu_maskwords_ - 1;
        bloom_mask_bits = parser.elfFile.objectSize == ElfFile.CLASS_32 ? 32 : 64;
    }

    /**
     * This method doesn't work every time and is unreliable. Use ELFSection.getELFSymbol(String) to retrieve symbols by
     * name. NOTE: since this method is currently broken it will always return null.
     */
    @Override
    public ElfSymbol getSymbol(ElfSymbolStructure symbolStructure, String symbolName) throws IOException {
        if (symbolName == null) {
            return null;
        }

        final long hash = elf_hash(symbolName);
        final long h2 = hash >> shift2;

        long word_num = (hash / bloom_mask_bits) & maskwords;
        long bloom_word = bloom_filters[(int) word_num];

        // test against bloom filter
        if ((1 & (bloom_word >> (hash % bloom_mask_bits)) & (bloom_word >> (h2 % bloom_mask_bits))) == 0) {
            return null;
        }

        // bloom test says "probably yes"...
        int n = buckets[(int) (hash % nbucket)];
        if (n == 0) {
            return null;
        }

        do {
            ElfSymbol symbol = symbolStructure.getELFSymbol(n);
            if (symbolName.equals(symbol.getName())) {
                return symbol;
            }
        } while ((chains.chain(n++) & 1) == 0);

        return null;
    }

    private static long elf_hash(String name) {
        long h = 5381;

        for(char c : name.toCharArray()) {
            h += (h << 5) + c; // h*33 + c = h + h * 32 + c = h + h << 5 + c
        }
        return h & 0xffffffffL;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy