com.facebook.buck.cxx.elf.ElfVerNeed.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.buck.cxx.elf.ElfVerNeed.java

Source

/*
 * Copyright 2016-present Facebook, Inc.
 *
 * 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 com.facebook.buck.cxx.elf;

import com.facebook.buck.model.Pair;
import com.facebook.buck.util.MoreIterables;
import com.facebook.buck.util.RichStream;
import com.google.common.collect.ImmutableList;

import java.nio.ByteBuffer;

public class ElfVerNeed {

    public final ImmutableList<Pair<Verneed, ImmutableList<Vernaux>>> entries;

    public ElfVerNeed(ImmutableList<Pair<Verneed, ImmutableList<Vernaux>>> entries) {
        this.entries = entries;
    }

    public static ElfVerNeed parse(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
        ImmutableList.Builder<Pair<Verneed, ImmutableList<Vernaux>>> entries = ImmutableList.builder();
        int vnPos = buffer.position();
        while (true) {
            buffer.position(vnPos);
            Verneed verneed = Verneed.parse(eiClass, buffer);
            int vnaPos = vnPos + (int) verneed.vn_aux;
            ImmutableList.Builder<Vernaux> vernauxEntries = ImmutableList.builder();
            for (int j = 0; j < verneed.vn_cnt; j++) {
                buffer.position(vnaPos);
                Vernaux vernaux = Vernaux.parse(eiClass, buffer);
                vernauxEntries.add(vernaux);
                vnaPos += (int) vernaux.vna_next;
            }
            entries.add(new Pair<>(verneed, vernauxEntries.build()));
            if (verneed.vn_next == 0) {
                break;
            }
            vnPos += verneed.vn_next;
        }
        return new ElfVerNeed(entries.build());
    }

    public void write(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
        int vnPos = buffer.position();
        for (Pair<Verneed, ImmutableList<Vernaux>> entry : entries) {
            Verneed verneed = entry.getFirst();
            ImmutableList<Vernaux> vernauxEntries = entry.getSecond();
            buffer.position(vnPos);
            verneed.write(eiClass, buffer);
            int vnaPos = vnPos + (int) verneed.vn_aux;
            for (Vernaux vernaux : vernauxEntries) {
                buffer.position(vnaPos);
                vernaux.write(eiClass, buffer);
                vnaPos += vernaux.vna_next;
            }
            vnPos += verneed.vn_next;
        }
    }

    public ElfVerNeed compact() {
        return new ElfVerNeed(RichStream.from(MoreIterables.enumerate(this.entries)).map(vnp -> {
            int verneedIndex = vnp.getFirst();
            ElfVerNeed.Verneed verneed = vnp.getSecond().getFirst();
            ImmutableList<ElfVerNeed.Vernaux> vernauxes = vnp.getSecond().getSecond();
            return new Pair<>(
                    new ElfVerNeed.Verneed(verneed.vn_version, vernauxes.size(), verneed.vn_file,
                            vernauxes.size() == 0 ? 0 : ElfVerNeed.Verneed.BYTES,
                            verneedIndex == entries.size() - 1 ? 0
                                    : ElfVerNeed.Verneed.BYTES + ElfVerNeed.Vernaux.BYTES * vernauxes.size()),
                    RichStream.from(MoreIterables.enumerate(vernauxes))
                            .map(vnxp -> new ElfVerNeed.Vernaux(vnxp.getSecond().vna_hash,
                                    vnxp.getSecond().vna_flags, vnxp.getSecond().vna_other,
                                    vnxp.getSecond().vna_name,
                                    vnxp.getFirst() == vernauxes.size() - 1 ? 0 : ElfVerNeed.Vernaux.BYTES))
                            .toImmutableList());
        }).toImmutableList());
    }

    public static class Verneed {

        private static final int BYTES = 16;

        // CHECKSTYLE.OFF: MemberName
        public final int vn_version;
        public final int vn_cnt;
        public final long vn_file;
        public final long vn_aux;
        public final long vn_next;
        // CHECKSTYLE.ON: MemberName

        // CHECKSTYLE.OFF: ParameterName
        public Verneed(int vn_version, int vn_cnt, long vn_file, long vn_aux, long vn_next) {
            this.vn_version = vn_version;
            this.vn_cnt = vn_cnt;
            this.vn_file = vn_file;
            this.vn_aux = vn_aux;
            this.vn_next = vn_next;
        }
        // CHECKSTYLE.ON: ParameterName

        private static Verneed parse(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
            if (eiClass == ElfHeader.EIClass.ELFCLASS32) {
                return new Verneed(Elf.Elf32.getElf32Half(buffer), Elf.Elf32.getElf32Half(buffer),
                        Elf.Elf32.getElf32Word(buffer), Elf.Elf32.getElf32Word(buffer),
                        Elf.Elf32.getElf32Word(buffer));
            } else {
                return new Verneed(Elf.Elf64.getElf64Half(buffer), Elf.Elf64.getElf64Half(buffer),
                        Elf.Elf64.getElf64Word(buffer), Elf.Elf64.getElf64Word(buffer),
                        Elf.Elf64.getElf64Word(buffer));
            }
        }

        private void write(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
            if (eiClass == ElfHeader.EIClass.ELFCLASS32) {
                Elf.Elf32.putElf32Half(buffer, (short) vn_version);
                Elf.Elf32.putElf32Half(buffer, (short) vn_cnt);
                Elf.Elf32.putElf32Word(buffer, (int) vn_file);
                Elf.Elf32.putElf32Word(buffer, (int) vn_aux);
                Elf.Elf32.putElf32Word(buffer, (int) vn_next);
            } else {
                Elf.Elf64.putElf64Half(buffer, (short) vn_version);
                Elf.Elf64.putElf64Half(buffer, (short) vn_cnt);
                Elf.Elf64.putElf64Word(buffer, (int) vn_file);
                Elf.Elf64.putElf64Word(buffer, (int) vn_aux);
                Elf.Elf64.putElf64Word(buffer, (int) vn_next);
            }
        }

    }

    public static class Vernaux {

        private static final int BYTES = 16;

        // CHECKSTYLE.OFF: MemberName
        public final long vna_hash;
        public final int vna_flags;
        public final int vna_other;
        public final long vna_name;
        public final long vna_next;
        // CHECKSTYLE.ON: MemberName

        // CHECKSTYLE.OFF: ParameterName
        public Vernaux(long vna_hash, int vna_flags, int vna_other, long vna_name, long vna_next) {
            this.vna_hash = vna_hash;
            this.vna_flags = vna_flags;
            this.vna_other = vna_other;
            this.vna_name = vna_name;
            this.vna_next = vna_next;
        }
        // CHECKSTYLE.ON: ParameterName

        private static Vernaux parse(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
            if (eiClass == ElfHeader.EIClass.ELFCLASS32) {
                return new Vernaux(Elf.Elf32.getElf32Word(buffer), Elf.Elf32.getElf32Half(buffer),
                        Elf.Elf32.getElf32Half(buffer), Elf.Elf32.getElf32Word(buffer),
                        Elf.Elf32.getElf32Word(buffer));
            } else {
                return new Vernaux(Elf.Elf64.getElf64Word(buffer), Elf.Elf64.getElf64Half(buffer),
                        Elf.Elf64.getElf64Half(buffer), Elf.Elf64.getElf64Word(buffer),
                        Elf.Elf64.getElf64Word(buffer));
            }
        }

        private void write(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
            if (eiClass == ElfHeader.EIClass.ELFCLASS32) {
                Elf.Elf32.putElf32Word(buffer, (int) vna_hash);
                Elf.Elf32.putElf32Half(buffer, (short) vna_flags);
                Elf.Elf32.putElf32Half(buffer, (short) vna_other);
                Elf.Elf32.putElf32Word(buffer, (int) vna_name);
                Elf.Elf32.putElf32Word(buffer, (int) vna_next);
            } else {
                Elf.Elf64.putElf64Word(buffer, (int) vna_hash);
                Elf.Elf64.putElf64Half(buffer, (short) vna_flags);
                Elf.Elf64.putElf64Half(buffer, (short) vna_other);
                Elf.Elf64.putElf64Word(buffer, (int) vna_name);
                Elf.Elf64.putElf64Word(buffer, (int) vna_next);
            }
        }

    }

}