/*
 * Copyright (C) 2024 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 "DynamicInstrumentationManager.h"
#include "DebugLog.h"
#include <android-base/logging.h>
#include <android-base/scopeguard.h>
#include <assert.h>
#include <dlfcn.h>
#include <log/log.h>
#include <optional>
#include <string>
#include <vector>

namespace android::uprobestats::dynamic_instrumentation_manager {

struct ADynamicInstrumentationManager_MethodDescriptor;
typedef struct ADynamicInstrumentationManager_MethodDescriptor
    ADynamicInstrumentationManager_MethodDescriptor;

struct ADynamicInstrumentationManager_TargetProcess;
typedef struct ADynamicInstrumentationManager_TargetProcess
    ADynamicInstrumentationManager_TargetProcess;

struct ADynamicInstrumentationManager_ExecutableMethodFileOffsets;
typedef struct ADynamicInstrumentationManager_ExecutableMethodFileOffsets
    ADynamicInstrumentationManager_ExecutableMethodFileOffsets;

typedef ADynamicInstrumentationManager_TargetProcess *(
    *ADynamicInstrumentationManager_TargetProcess_create)(
    uid_t uid, pid_t pid, const char *processName);
typedef void (*ADynamicInstrumentationManager_TargetProcess_destroy)(
    const ADynamicInstrumentationManager_TargetProcess *instance);

typedef ADynamicInstrumentationManager_MethodDescriptor *(
    *ADynamicInstrumentationManager_MethodDescriptor_create)(
    const char *fullyQualifiedClassName, const char *methodName,
    const char *fullyQualifiedParameters[], unsigned int numParameters);
typedef void (*ADynamicInstrumentationManager_MethodDescriptor_destroy)(
    const ADynamicInstrumentationManager_MethodDescriptor *instance);

typedef const char *(
    *ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath)(
    const ADynamicInstrumentationManager_ExecutableMethodFileOffsets *instance);
typedef unsigned long (
    *ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset)(
    const ADynamicInstrumentationManager_ExecutableMethodFileOffsets *instance);
typedef unsigned long (
    *ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset)(
    const ADynamicInstrumentationManager_ExecutableMethodFileOffsets *instance);
typedef void (
    *ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy)(
    const ADynamicInstrumentationManager_ExecutableMethodFileOffsets *instance);

typedef int32_t (
    *ADynamicInstrumentationManager_getExecutableMethodFileOffsets)(
    const ADynamicInstrumentationManager_TargetProcess &targetProcess,
    const ADynamicInstrumentationManager_MethodDescriptor &methodDescriptor,
    const ADynamicInstrumentationManager_ExecutableMethodFileOffsets **out);

const char kLibandroidPath[] = "libandroid.so";

template <typename T>
void getLibFunction(void *handle, const char *identifier, T *out) {
  auto result = reinterpret_cast<T>(dlsym(handle, identifier));
  if (!result) {
    ALOGE("dlsym error: %s %s %s", __func__, dlerror(), identifier);
    assert(result);
  }
  *out = result;
}

std::optional<ExecutableMethodFileOffsets>
getExecutableMethodFileOffsets(std::string &processName, std::string &fqcn,
                               std::string &methodName,
                               std::vector<std::string> &fqParameters) {
  void *handle = dlopen(kLibandroidPath, RTLD_NOW | RTLD_LOCAL);
  if (!handle) {
    ALOGE("dlopen error: %s %s", __func__, dlerror());
    return {};
  }

  ADynamicInstrumentationManager_TargetProcess_create targetProcess_create;
  getLibFunction(handle, "ADynamicInstrumentationManager_TargetProcess_create",
                 &targetProcess_create);
  ADynamicInstrumentationManager_TargetProcess_destroy targetProcess_destroy;
  getLibFunction(handle, "ADynamicInstrumentationManager_TargetProcess_destroy",
                 &targetProcess_destroy);
  ADynamicInstrumentationManager_MethodDescriptor_create
      methodDescriptor_create;
  getLibFunction(handle,
                 "ADynamicInstrumentationManager_MethodDescriptor_create",
                 &methodDescriptor_create);
  ADynamicInstrumentationManager_MethodDescriptor_destroy
      methodDescriptor_destroy;
  getLibFunction(handle,
                 "ADynamicInstrumentationManager_MethodDescriptor_destroy",
                 &methodDescriptor_destroy);
  ADynamicInstrumentationManager_getExecutableMethodFileOffsets
      getExecutableMethodFileOffsets;
  getLibFunction(
      handle, "ADynamicInstrumentationManager_getExecutableMethodFileOffsets",
      &getExecutableMethodFileOffsets);
  ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy
      executableMethodFileOffsets_destroy;
  getLibFunction(
      handle,
      "ADynamicInstrumentationManager_ExecutableMethodFileOffsets_destroy",
      &executableMethodFileOffsets_destroy);
  ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerPath
      getContainerPath;
  getLibFunction(handle,
                 "ADynamicInstrumentationManager_ExecutableMethodFileOffsets_"
                 "getContainerPath",
                 &getContainerPath);
  ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getContainerOffset
      getContainerOffset;
  getLibFunction(handle,
                 "ADynamicInstrumentationManager_ExecutableMethodFileOffsets_"
                 "getContainerOffset",
                 &getContainerOffset);
  ADynamicInstrumentationManager_ExecutableMethodFileOffsets_getMethodOffset
      getMethodOffset;
  getLibFunction(handle,
                 "ADynamicInstrumentationManager_ExecutableMethodFileOffsets_"
                 "getMethodOffset",
                 &getMethodOffset);

  const ADynamicInstrumentationManager_TargetProcess *targetProcess =
      targetProcess_create(0, 0, processName.c_str());

  std::vector<const char *> fqpVec;
  for (size_t i = 0; i < fqParameters.size(); ++i) {
    fqpVec.push_back(fqParameters[i].c_str());
  }
  const ADynamicInstrumentationManager_MethodDescriptor *methodDescriptor =
      methodDescriptor_create(fqcn.c_str(), methodName.c_str(), fqpVec.data(),
                              fqParameters.size());

  const ADynamicInstrumentationManager_ExecutableMethodFileOffsets *offsets =
      nullptr;
  int32_t result = getExecutableMethodFileOffsets(*targetProcess,
                                                  *methodDescriptor, &offsets);

  targetProcess_destroy(targetProcess);
  methodDescriptor_destroy(methodDescriptor);

  if (result != 0) {
    LOG(ERROR) << "error calling getExecutableMethodFileOffsets. result: "
               << result;
  }

  if (offsets == nullptr) {
    LOG(ERROR) << "could not find offset for " << methodName;
    return {};
  }

  const char *cp = getContainerPath(offsets);
  std::string containerPath(cp);
  uint64_t containerOffset = getContainerOffset(offsets);
  uint64_t methodOffset = getMethodOffset(offsets);

  executableMethodFileOffsets_destroy(offsets);

  ExecutableMethodFileOffsets executableMethodFileOffsets;
  executableMethodFileOffsets.containerPath = containerPath;
  executableMethodFileOffsets.containerOffset = containerOffset;
  executableMethodFileOffsets.methodOffset = methodOffset;
  return executableMethodFileOffsets;
}
} // namespace android::uprobestats::dynamic_instrumentation_manager
