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

Java tutorial

Introduction

Here is the source code for com.facebook.buck.cxx.elf.ElfVerDef.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 ElfVerDef {

    public final ImmutableList<Pair<Verdef, ImmutableList<Verdaux>>> entries;

    public ElfVerDef(ImmutableList<Pair<Verdef, ImmutableList<Verdaux>>> entries) {
        this.entries = entries;
    }

    public static ElfVerDef parse(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
        ImmutableList.Builder<Pair<Verdef, ImmutableList<Verdaux>>> entries = ImmutableList.builder();
        int vdPos = buffer.position();
        while (buffer.hasRemaining()) {
            buffer.position(vdPos);
            Verdef verdef = Verdef.parse(eiClass, buffer);
            int vdaPos = vdPos + (int) verdef.vd_aux;
            ImmutableList.Builder<Verdaux> verdauxEntries = ImmutableList.builder();
            for (int j = 0; j < verdef.vd_cnt; j++) {
                buffer.position(vdaPos);
                Verdaux verdaux = Verdaux.parse(eiClass, buffer);
                verdauxEntries.add(verdaux);
                vdaPos += (int) verdaux.vda_next;
            }
            entries.add(new Pair<>(verdef, verdauxEntries.build()));
            if (verdef.vd_next == 0) {
                break;
            }
            vdPos += verdef.vd_next;
        }
        return new ElfVerDef(entries.build());
    }

    public void write(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
        int vdPos = buffer.position();
        for (Pair<Verdef, ImmutableList<Verdaux>> entry : entries) {
            Verdef verdef = entry.getFirst();
            ImmutableList<Verdaux> verdauxEntries = entry.getSecond();
            buffer.position(vdPos);
            verdef.write(eiClass, buffer);
            int vdaPos = vdPos + (int) verdef.vd_aux;
            for (Verdaux verdaux : verdauxEntries) {
                buffer.position(vdaPos);
                verdaux.write(eiClass, buffer);
                vdaPos += verdaux.vda_next;
            }
            vdPos += verdef.vd_next;
        }
    }

    public ElfVerDef compact() {
        return new ElfVerDef(RichStream.from(MoreIterables.enumerate(this.entries)).map(vdp -> {
            int verdefIndex = vdp.getFirst();
            Verdef verdef = vdp.getSecond().getFirst();
            ImmutableList<Verdaux> verdauxes = vdp.getSecond().getSecond();
            return new Pair<>(
                    new Verdef(verdef.vd_version, verdef.vd_flags, verdef.vd_ndx, verdauxes.size(), verdef.vd_hash,
                            verdauxes.size() == 0 ? 0 : Verdef.BYTES,
                            verdefIndex == entries.size() - 1 ? 0
                                    : Verdef.BYTES + Verdaux.BYTES * verdauxes.size()),
                    RichStream.from(MoreIterables.enumerate(verdauxes))
                            .map(vdxp -> new Verdaux(vdxp.getSecond().vda_name,
                                    vdxp.getFirst() == verdauxes.size() - 1 ? 0 : Verdaux.BYTES))
                            .toImmutableList());
        }).toImmutableList());
    }

    public static class Verdef {

        private static final int BYTES = 20;

        // CHECKSTYLE.OFF: MemberName
        public final int vd_version;
        public final int vd_flags;
        public final int vd_ndx;
        public final int vd_cnt;
        public final long vd_hash;
        public final long vd_aux;
        public final long vd_next;
        // CHECKSTYLE.ON: MemberName

        // CHECKSTYLE.OFF: ParameterName
        public Verdef(int vd_version, int vd_flags, int vd_ndx, int vd_cnt, long vd_hash, long vd_aux,
                long vd_next) {
            this.vd_version = vd_version;
            this.vd_flags = vd_flags;
            this.vd_ndx = vd_ndx;
            this.vd_cnt = vd_cnt;
            this.vd_hash = vd_hash;
            this.vd_aux = vd_aux;
            this.vd_next = vd_next;
        }
        // CHECKSTYLE.ON: ParameterName

        private static Verdef parse(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
            if (eiClass == ElfHeader.EIClass.ELFCLASS32) {
                return new Verdef(Elf.Elf32.getElf32Half(buffer), Elf.Elf32.getElf32Half(buffer),
                        Elf.Elf32.getElf32Half(buffer), Elf.Elf32.getElf32Half(buffer),
                        Elf.Elf32.getElf32Word(buffer), Elf.Elf32.getElf32Word(buffer),
                        Elf.Elf32.getElf32Word(buffer));
            } else {
                return new Verdef(Elf.Elf64.getElf64Half(buffer), Elf.Elf64.getElf64Half(buffer),
                        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) vd_version);
                Elf.Elf32.putElf32Half(buffer, (short) vd_flags);
                Elf.Elf32.putElf32Half(buffer, (short) vd_ndx);
                Elf.Elf32.putElf32Half(buffer, (short) vd_cnt);
                Elf.Elf32.putElf32Word(buffer, (int) vd_hash);
                Elf.Elf32.putElf32Word(buffer, (int) vd_aux);
                Elf.Elf32.putElf32Word(buffer, (int) vd_next);
            } else {
                Elf.Elf64.putElf64Half(buffer, (short) vd_version);
                Elf.Elf64.putElf64Half(buffer, (short) vd_flags);
                Elf.Elf64.putElf64Half(buffer, (short) vd_ndx);
                Elf.Elf64.putElf64Half(buffer, (short) vd_cnt);
                Elf.Elf64.putElf64Word(buffer, (int) vd_hash);
                Elf.Elf64.putElf64Word(buffer, (int) vd_aux);
                Elf.Elf64.putElf64Word(buffer, (int) vd_next);
            }
        }

    }

    public static class Verdaux {

        private static final int BYTES = 8;

        // CHECKSTYLE.OFF: MemberName
        public final long vda_name;
        public final long vda_next;
        // CHECKSTYLE.ON: MemberName

        // CHECKSTYLE.OFF: ParameterName
        public Verdaux(long vda_name, long vda_next) {
            this.vda_name = vda_name;
            this.vda_next = vda_next;
        }
        // CHECKSTYLE.ON: ParameterName

        private static Verdaux parse(ElfHeader.EIClass eiClass, ByteBuffer buffer) {
            if (eiClass == ElfHeader.EIClass.ELFCLASS32) {
                return new Verdaux(Elf.Elf32.getElf32Word(buffer), Elf.Elf32.getElf32Word(buffer));
            } else {
                return new Verdaux(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) vda_name);
                Elf.Elf32.putElf32Word(buffer, (int) vda_next);
            } else {
                Elf.Elf64.putElf64Word(buffer, (int) vda_name);
                Elf.Elf64.putElf64Word(buffer, (int) vda_next);
            }
        }

    }

}