Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d312abe7 authored by Christopher Ferris's avatar Christopher Ferris Committed by Gerrit Code Review
Browse files

Merge "Move tools to separate directory."

parents 454285df b5d7a875
Loading
Loading
Loading
Loading
+28 −6
Original line number Original line Diff line number Diff line
@@ -150,10 +150,10 @@ cc_test {
}
}


//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
// Utility Executables
// Tools
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
cc_defaults {
cc_defaults {
    name: "libunwindstack_executables",
    name: "libunwindstack_tools",
    defaults: ["libunwindstack_flags"],
    defaults: ["libunwindstack_flags"],


    shared_libs: [
    shared_libs: [
@@ -161,18 +161,40 @@ cc_defaults {
        "libbase",
        "libbase",
        "liblzma",
        "liblzma",
    ],
    ],
}


    static_libs: [
cc_binary {
        "liblog",
    name: "unwind",
    defaults: ["libunwindstack_tools"],

    srcs: [
        "tools/unwind.cpp",
    ],

    target: {
        linux: {
            host_ldlibs: [
                "-lrt",
            ],
            ],
        },
    },
}
}


cc_binary {
cc_binary {
    name: "unwind_info",
    name: "unwind_info",
    defaults: ["libunwindstack_executables"],
    defaults: ["libunwindstack_tools"],

    srcs: [
        "tools/unwind_info.cpp",
    ],
}

cc_binary {
    name: "unwind_symbols",
    defaults: ["libunwindstack_tools"],


    srcs: [
    srcs: [
        "unwind_info.cpp",
        "tools/unwind_symbols.cpp",
    ],
    ],
}
}


+160 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2016 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 <errno.h>
#include <inttypes.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <unistd.h>

#include <string>

#include "Elf.h"
#include "Maps.h"
#include "Memory.h"
#include "Regs.h"

static bool Attach(pid_t pid) {
  if (ptrace(PTRACE_ATTACH, pid, 0, 0) == -1) {
    return false;
  }

  // Allow at least 1 second to attach properly.
  for (size_t i = 0; i < 1000; i++) {
    siginfo_t si;
    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == 0) {
      return true;
    }
    usleep(1000);
  }
  printf("%d: Failed to stop.\n", pid);
  return false;
}

static bool Detach(pid_t pid) {
  return ptrace(PTRACE_DETACH, pid, 0, 0) == 0;
}

void DoUnwind(pid_t pid) {
  RemoteMaps remote_maps(pid);
  if (!remote_maps.Parse()) {
    printf("Failed to parse map data.\n");
    return;
  }

  uint32_t machine_type;
  Regs* regs = Regs::RemoteGet(pid, &machine_type);
  if (regs == nullptr) {
    printf("Unable to get remote reg data\n");
    return;
  }

  bool bits32 = true;
  printf("ABI: ");
  switch (machine_type) {
    case EM_ARM:
      printf("arm");
      break;
    case EM_386:
      printf("x86");
      break;
    case EM_AARCH64:
      printf("arm64");
      bits32 = false;
      break;
    case EM_X86_64:
      printf("x86_64");
      bits32 = false;
      break;
    default:
      printf("unknown\n");
      return;
  }
  printf("\n");

  MemoryRemote remote_memory(pid);
  for (size_t frame_num = 0; frame_num < 64; frame_num++) {
    if (regs->pc() == 0) {
      break;
    }
    MapInfo* map_info = remote_maps.Find(regs->pc());
    if (map_info == nullptr) {
      printf("Failed to find map data for the pc\n");
      break;
    }

    Elf* elf = map_info->GetElf(pid, true);

    uint64_t rel_pc = regs->GetRelPc(elf, map_info);
    uint64_t adjusted_rel_pc = rel_pc;
    // Don't need to adjust the first frame pc.
    if (frame_num != 0) {
      adjusted_rel_pc = regs->GetAdjustedPc(rel_pc, elf);
    }

    std::string name;
    if (bits32) {
      printf("  #%02zu pc %08" PRIx64, frame_num, adjusted_rel_pc);
    } else {
      printf("  #%02zu pc %016" PRIx64, frame_num, adjusted_rel_pc);
    }
    if (!map_info->name.empty()) {
      printf("  %s", map_info->name.c_str());
      if (map_info->elf_offset != 0) {
        printf(" (offset 0x%" PRIx64 ")", map_info->elf_offset);
      }
    } else {
      printf("  <anonymous:%" PRIx64 ">", map_info->offset);
    }
    uint64_t func_offset;
    if (elf->GetFunctionName(adjusted_rel_pc, &name, &func_offset)) {
      printf(" (%s", name.c_str());
      if (func_offset != 0) {
        printf("+%" PRId64, func_offset);
      }
      printf(")");
    }
    printf("\n");

    if (!elf->Step(rel_pc + map_info->elf_offset, regs, &remote_memory)) {
      break;
    }
  }
}

int main(int argc, char** argv) {
  if (argc != 2) {
    printf("Usage: unwind <PID>\n");
    return 1;
  }

  pid_t pid = atoi(argv[1]);
  if (!Attach(pid)) {
    printf("Failed to attach to pid %d: %s\n", pid, strerror(errno));
    return 1;
  }

  DoUnwind(pid);

  Detach(pid);

  return 0;
}
+1 −5
Original line number Original line Diff line number Diff line
@@ -21,8 +21,8 @@
#include <stdio.h>
#include <stdio.h>
#include <string.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <unistd.h>


#include "ArmExidx.h"
#include "ArmExidx.h"
@@ -115,10 +115,6 @@ int main(int argc, char** argv) {
    printf("%s is not a regular file.\n", argv[1]);
    printf("%s is not a regular file.\n", argv[1]);
    return 1;
    return 1;
  }
  }
  if (S_ISDIR(st.st_mode)) {
    printf("%s is a directory.\n", argv[1]);
    return 1;
  }


  // Send all log messages to stdout.
  // Send all log messages to stdout.
  log_to_stdout(true);
  log_to_stdout(true);
+97 −0
Original line number Original line Diff line number Diff line
/*
 * Copyright (C) 2016 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 <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "Elf.h"
#include "ElfInterface.h"
#include "Log.h"

int main(int argc, char** argv) {
  if (argc != 2) {
    printf("Need to pass the name of an elf file to the program.\n");
    return 1;
  }

  struct stat st;
  if (stat(argv[1], &st) == -1) {
    printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
    return 1;
  }
  if (!S_ISREG(st.st_mode)) {
    printf("%s is not a regular file.\n", argv[1]);
    return 1;
  }

  // Send all log messages to stdout.
  log_to_stdout(true);

  MemoryFileAtOffset* memory = new MemoryFileAtOffset;
  if (!memory->Init(argv[1], 0)) {
    printf("Failed to init\n");
    return 1;
  }

  Elf elf(memory);
  if (!elf.Init() || !elf.valid()) {
    printf("%s is not a valid elf file.\n", argv[1]);
    return 1;
  }

  switch (elf.machine_type()) {
    case EM_ARM:
      printf("ABI: arm\n");
      break;
    case EM_AARCH64:
      printf("ABI: arm64\n");
      break;
    case EM_386:
      printf("ABI: x86\n");
      break;
    case EM_X86_64:
      printf("ABI: x86_64\n");
      break;
    default:
      printf("ABI: unknown\n");
      return 1;
  }

  // This is a crude way to get the symbols in order.
  std::string name;
  uint64_t load_bias = elf.interface()->load_bias();
  for (const auto& entry : elf.interface()->pt_loads()) {
    uint64_t start = entry.second.offset + load_bias;
    uint64_t end = entry.second.table_size + load_bias;
    for (uint64_t addr = start; addr < end; addr += 4) {
      std::string cur_name;
      uint64_t func_offset;
      if (elf.GetFunctionName(addr, &cur_name, &func_offset)) {
        if (cur_name != name) {
          printf("<0x%" PRIx64 "> Function: %s\n", addr - func_offset, cur_name.c_str());
        }
        name = cur_name;
      }
    }
  }

  return 0;
}