/*
 * Copyright (C) 2017 The Android Open Source Project
 *
 * 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.
 */

#include <assert.h>
#include <stdint.h>

#include <string>

#include "DwarfEncoding.h"
#include "DwarfMemory.h"
#include "Memory.h"

bool DwarfMemory::ReadBytes(void* dst, size_t num_bytes) {
  if (!memory_->Read(cur_offset_, dst, num_bytes)) {
    return false;
  }
  cur_offset_ += num_bytes;
  return true;
}

template <typename SignedType>
bool DwarfMemory::ReadSigned(uint64_t* value) {
  SignedType signed_value;
  if (!ReadBytes(&signed_value, sizeof(SignedType))) {
    return false;
  }
  *value = static_cast<int64_t>(signed_value);
  return true;
}

bool DwarfMemory::ReadULEB128(uint64_t* value) {
  uint64_t cur_value = 0;
  uint64_t shift = 0;
  uint8_t byte;
  do {
    if (!ReadBytes(&byte, 1)) {
      return false;
    }
    cur_value += static_cast<uint64_t>(byte & 0x7f) << shift;
    shift += 7;
  } while (byte & 0x80);
  *value = cur_value;
  return true;
}

bool DwarfMemory::ReadSLEB128(int64_t* value) {
  uint64_t cur_value = 0;
  uint64_t shift = 0;
  uint8_t byte;
  do {
    if (!ReadBytes(&byte, 1)) {
      return false;
    }
    cur_value += static_cast<uint64_t>(byte & 0x7f) << shift;
    shift += 7;
  } while (byte & 0x80);
  if (byte & 0x40) {
    // Negative value, need to sign extend.
    cur_value |= static_cast<uint64_t>(-1) << shift;
  }
  *value = static_cast<int64_t>(cur_value);
  return true;
}

template <typename AddressType>
size_t DwarfMemory::GetEncodedSize(uint8_t encoding) {
  switch (encoding & 0x0f) {
    case DW_EH_PE_absptr:
      return sizeof(AddressType);
    case DW_EH_PE_udata1:
    case DW_EH_PE_sdata1:
      return 1;
    case DW_EH_PE_udata2:
    case DW_EH_PE_sdata2:
      return 2;
    case DW_EH_PE_udata4:
    case DW_EH_PE_sdata4:
      return 4;
    case DW_EH_PE_udata8:
    case DW_EH_PE_sdata8:
      return 8;
    case DW_EH_PE_uleb128:
    case DW_EH_PE_sleb128:
    default:
      return 0;
  }
}

bool DwarfMemory::AdjustEncodedValue(uint8_t encoding, uint64_t* value) {
  assert((encoding & 0x0f) == 0);
  assert(encoding != DW_EH_PE_aligned);

  // Handle the encoding.
  switch (encoding) {
    case DW_EH_PE_absptr:
      // Nothing to do.
      break;
    case DW_EH_PE_pcrel:
      if (pc_offset_ == static_cast<uint64_t>(-1)) {
        // Unsupported encoding.
        return false;
      }
      *value += pc_offset_;
      break;
    case DW_EH_PE_textrel:
      if (text_offset_ == static_cast<uint64_t>(-1)) {
        // Unsupported encoding.
        return false;
      }
      *value += text_offset_;
      break;
    case DW_EH_PE_datarel:
      if (data_offset_ == static_cast<uint64_t>(-1)) {
        // Unsupported encoding.
        return false;
      }
      *value += data_offset_;
      break;
    case DW_EH_PE_funcrel:
      if (func_offset_ == static_cast<uint64_t>(-1)) {
        // Unsupported encoding.
        return false;
      }
      *value += func_offset_;
      break;
    default:
      return false;
  }

  return true;
}

template <typename AddressType>
bool DwarfMemory::ReadEncodedValue(uint8_t encoding, uint64_t* value) {
  if (encoding == DW_EH_PE_omit) {
    *value = 0;
    return true;
  } else if (encoding == DW_EH_PE_aligned) {
    if (__builtin_add_overflow(cur_offset_, sizeof(AddressType) - 1, &cur_offset_)) {
      return false;
    }
    cur_offset_ &= -sizeof(AddressType);

    if (sizeof(AddressType) != sizeof(uint64_t)) {
      *value = 0;
    }
    return ReadBytes(value, sizeof(AddressType));
  }

  // Get the data.
  switch (encoding & 0x0f) {
    case DW_EH_PE_absptr:
      if (sizeof(AddressType) != sizeof(uint64_t)) {
        *value = 0;
      }
      if (!ReadBytes(value, sizeof(AddressType))) {
        return false;
      }
      break;
    case DW_EH_PE_uleb128:
      if (!ReadULEB128(value)) {
        return false;
      }
      break;
    case DW_EH_PE_sleb128:
      int64_t signed_value;
      if (!ReadSLEB128(&signed_value)) {
        return false;
      }
      *value = static_cast<uint64_t>(signed_value);
      break;
    case DW_EH_PE_udata1: {
      uint8_t value8;
      if (!ReadBytes(&value8, 1)) {
        return false;
      }
      *value = value8;
    } break;
    case DW_EH_PE_sdata1:
      if (!ReadSigned<int8_t>(value)) {
        return false;
      }
      break;
    case DW_EH_PE_udata2: {
      uint16_t value16;
      if (!ReadBytes(&value16, 2)) {
        return false;
      }
      *value = value16;
    } break;
    case DW_EH_PE_sdata2:
      if (!ReadSigned<int16_t>(value)) {
        return false;
      }
      break;
    case DW_EH_PE_udata4: {
      uint32_t value32;
      if (!ReadBytes(&value32, 4)) {
        return false;
      }
      *value = value32;
    } break;
    case DW_EH_PE_sdata4:
      if (!ReadSigned<int32_t>(value)) {
        return false;
      }
      break;
    case DW_EH_PE_udata8:
      if (!ReadBytes(value, sizeof(uint64_t))) {
        return false;
      }
      break;
    case DW_EH_PE_sdata8:
      if (!ReadSigned<int64_t>(value)) {
        return false;
      }
      break;
    default:
      return false;
  }

  return AdjustEncodedValue(encoding & 0xf0, value);
}

// Instantiate all of the needed template functions.
template bool DwarfMemory::ReadSigned<int8_t>(uint64_t*);
template bool DwarfMemory::ReadSigned<int16_t>(uint64_t*);
template bool DwarfMemory::ReadSigned<int32_t>(uint64_t*);
template bool DwarfMemory::ReadSigned<int64_t>(uint64_t*);

template size_t DwarfMemory::GetEncodedSize<uint32_t>(uint8_t);
template size_t DwarfMemory::GetEncodedSize<uint64_t>(uint8_t);

template bool DwarfMemory::ReadEncodedValue<uint32_t>(uint8_t, uint64_t*);
template bool DwarfMemory::ReadEncodedValue<uint64_t>(uint8_t, uint64_t*);
