/* * 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.macho; import com.google.common.base.Preconditions; import com.google.common.primitives.UnsignedInteger; import com.google.common.primitives.UnsignedLong; import java.io.IOException; import java.nio.ByteBuffer; public class NlistUtils { private NlistUtils() {} public static int getSizeInBytes(boolean is64Bit) { if (is64Bit) { return Nlist.SIZE_IN_BYTES_64_BIT; } else { return Nlist.SIZE_IN_BYTES_32_BIT; } } /** * Reads Nlist entry for the given architecture from the buffer at the current position. * * @param buffer ByteBuffer with data, must be positioned properly. * @param is64Bit Indicator if architecture is 32 or 64 bits. * @return Nlist entry */ public static Nlist createFromBuffer(ByteBuffer buffer, boolean is64Bit) { return Nlist.of( buffer.position(), UnsignedInteger.fromIntBits(buffer.getInt()), UnsignedInteger.fromIntBits(buffer.get() & 0xFF), UnsignedInteger.fromIntBits(buffer.get() & 0xFF), UnsignedInteger.fromIntBits(buffer.getShort() & 0xFFFF), UnsignedLong.fromLongBits(is64Bit ? buffer.getLong() : buffer.getInt() & 0xFFFFFFFFL)); } /** * Writes the given Nlist to the buffer at the current position. * * @param nlist The Nlist instance to write to the buffer. * @param buffer ByteBuffer with data, must be positioned/resized properly. * @param is64Bit Indicator if architecture is 32 or 64 bits. */ public static void writeNlistToBuffer(Nlist nlist, ByteBuffer buffer, boolean is64Bit) { buffer .putInt(nlist.getN_strx().intValue()) .put(nlist.getN_type().byteValue()) .put(nlist.getN_sect().byteValue()) .putShort(nlist.getN_desc().shortValue()); if (is64Bit) { buffer.putLong(nlist.getN_value().longValue()); } else { buffer.putInt(nlist.getN_value().intValue()); } } /** * Takes existing Nlist entry and updates it with the new entry. * * @param buffer The buffer which holds all data. * @param original existing Nlist entry that needs to be updated in the buffer. * @param updated new Nlist entry that should replace old entry. * @param is64Bit Indicator if architecture is 32 or 64 bits. * @throws IOException */ public static void updateNlistEntry( ByteBuffer buffer, Nlist original, Nlist updated, boolean is64Bit) { Preconditions.checkArgument(original.getOffsetInBinary() == updated.getOffsetInBinary()); buffer.position(updated.getOffsetInBinary()); writeNlistToBuffer(updated, buffer, is64Bit); } }