1e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris/*
2e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * Copyright (C) 2018 The Android Open Source Project
3e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris *
4e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * Licensed under the Apache License, Version 2.0 (the "License");
5e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * you may not use this file except in compliance with the License.
6e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * You may obtain a copy of the License at
7e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris *
8e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris *      http://www.apache.org/licenses/LICENSE-2.0
9e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris *
10e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * Unless required by applicable law or agreed to in writing, software
11e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * distributed under the License is distributed on an "AS IS" BASIS,
12e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * See the License for the specific language governing permissions and
14e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris * limitations under the License.
15e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris */
16e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
17e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <elf.h>
18e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <errno.h>
19e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <fcntl.h>
20e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <inttypes.h>
21e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <stdio.h>
22e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <stdlib.h>
23e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <string.h>
24e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <sys/mman.h>
25e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <sys/stat.h>
26e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <sys/types.h>
27e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unistd.h>
28e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
29e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/DwarfLocation.h>
30e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/DwarfMemory.h>
31e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/DwarfSection.h>
32e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/DwarfStructs.h>
33e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/Elf.h>
34e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/ElfInterface.h>
35e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include <unwindstack/Log.h>
36e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
37e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris#include "DwarfOp.h"
38e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
39e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferrisnamespace unwindstack {
40e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
41e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferrisvoid PrintSignedValue(int64_t value) {
42e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (value < 0) {
43e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("- %" PRId64, -value);
44e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  } else if (value > 0) {
45e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("+ %" PRId64, value);
46e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
47e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris}
48e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
49e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferrisvoid PrintExpression(Memory* memory, uint8_t class_type, uint64_t end, uint64_t length) {
50e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  std::vector<std::string> lines;
51e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  DwarfMemory dwarf_memory(memory);
52e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (class_type == ELFCLASS32) {
53e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    DwarfOp<uint32_t> op(&dwarf_memory, nullptr);
54e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    op.GetLogInfo(end - length, end, &lines);
55e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  } else {
56e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    DwarfOp<uint64_t> op(&dwarf_memory, nullptr);
57e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    op.GetLogInfo(end - length, end, &lines);
58e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
59e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  for (auto& line : lines) {
60e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("    %s\n", line.c_str());
61e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
62e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris}
63e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
64e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferrisvoid PrintRegInformation(DwarfSection* section, Memory* memory, uint64_t pc, uint8_t class_type) {
65e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  const DwarfFde* fde = section->GetFdeFromPc(pc);
66e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (fde == nullptr) {
67e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("  No fde found.\n");
68e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return;
69e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
70e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
71e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  dwarf_loc_regs_t regs;
72e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (!section->GetCfaLocationInfo(pc, fde, &regs)) {
73e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("  Cannot get location information.\n");
74e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return;
75e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
76e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
77e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  std::vector<std::pair<uint32_t, DwarfLocation>> loc_regs;
78e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  for (auto& loc : regs) {
79e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    loc_regs.push_back(loc);
80e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
81e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  std::sort(loc_regs.begin(), loc_regs.end(), [](auto a, auto b) {
82e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    if (a.first == CFA_REG) {
83e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      return true;
84e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    } else if (b.first == CFA_REG) {
85e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      return false;
86e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    }
87e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return a.first < b.first;
88e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  });
89e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
90e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  for (auto& entry : loc_regs) {
91e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    const DwarfLocation* loc = &entry.second;
92e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    if (entry.first == CFA_REG) {
93e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("  cfa = ");
94e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    } else {
95e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("  r%d = ", entry.first);
96e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    }
97e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    switch (loc->type) {
98e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_OFFSET:
99e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("[cfa ");
100e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        PrintSignedValue(loc->values[0]);
101e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("]\n");
102e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
103e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
104e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_VAL_OFFSET:
105e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("cfa ");
106e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        PrintSignedValue(loc->values[0]);
107e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("\n");
108e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
109e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
110e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_REGISTER:
111e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("r%" PRId64 " ", loc->values[0]);
112e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        PrintSignedValue(loc->values[1]);
113e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("\n");
114e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
115e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
116e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_EXPRESSION: {
117e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("EXPRESSION\n");
118e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        PrintExpression(memory, class_type, loc->values[1], loc->values[0]);
119e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
120e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      }
121e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
122e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_VAL_EXPRESSION: {
123e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("VAL EXPRESSION\n");
124e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        PrintExpression(memory, class_type, loc->values[1], loc->values[0]);
125e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
126e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      }
127e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
128e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_UNDEFINED:
129e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("undefine\n");
130e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
131e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
132e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      case DWARF_LOCATION_INVALID:
133e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        printf("INVALID\n");
134e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris        break;
135e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    }
136e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
137e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris}
138e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
139e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferrisint GetInfo(const char* file, uint64_t pc) {
140e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  MemoryFileAtOffset* memory = new MemoryFileAtOffset;
141e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (!memory->Init(file, 0)) {
142e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    // Initializatation failed.
143e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("Failed to init\n");
144e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
145e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
146e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
147e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  Elf elf(memory);
148e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (!elf.Init(true) || !elf.valid()) {
149e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("%s is not a valid elf file.\n", file);
150e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
151e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
152e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
153e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  ElfInterface* interface = elf.interface();
154e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  uint64_t load_bias = elf.GetLoadBias();
155e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (pc < load_bias) {
156e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("PC is less than load bias.\n");
157e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
158e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
159e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
160beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris  std::string soname;
161beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris  if (elf.GetSoname(&soname)) {
162beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris    printf("Soname: %s\n\n", soname.c_str());
163beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris  }
164beae42bc7f8fb6494138ff8a6d17ed6a65b2cf9aChristopher Ferris
165e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  printf("PC 0x%" PRIx64 ":\n", pc);
166e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
167e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  DwarfSection* section = interface->eh_frame();
168e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (section != nullptr) {
169e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("\neh_frame:\n");
170e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    PrintRegInformation(section, memory, pc - load_bias, elf.class_type());
171e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  } else {
172e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("\nno eh_frame information\n");
173e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
174e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
175e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  section = interface->debug_frame();
176e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (section != nullptr) {
177e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("\ndebug_frame:\n");
178e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    PrintRegInformation(section, memory, pc - load_bias, elf.class_type());
179e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("\n");
180e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  } else {
181e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("\nno debug_frame information\n");
182e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
183e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
184e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  // If there is a gnu_debugdata interface, dump the information for that.
185e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  ElfInterface* gnu_debugdata_interface = elf.gnu_debugdata_interface();
186e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (gnu_debugdata_interface != nullptr) {
187e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    section = gnu_debugdata_interface->eh_frame();
188e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    if (section != nullptr) {
189e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("\ngnu_debugdata (eh_frame):\n");
190e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type());
191e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("\n");
192e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    } else {
193e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("\nno gnu_debugdata (eh_frame)\n");
194e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    }
195e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
196e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    section = gnu_debugdata_interface->debug_frame();
197e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    if (section != nullptr) {
198e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("\ngnu_debugdata (debug_frame):\n");
199e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      PrintRegInformation(section, gnu_debugdata_interface->memory(), pc, elf.class_type());
200e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("\n");
201e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    } else {
202e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris      printf("\nno gnu_debugdata (debug_frame)\n");
203e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    }
204e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  } else {
205e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("\nno valid gnu_debugdata information\n");
206e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
207e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
208e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  return 0;
209e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris}
210e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
211e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris}  // namespace unwindstack
212e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
213e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferrisint main(int argc, char** argv) {
214e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (argc != 3) {
215e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("Usage: unwind_reg_info ELF_FILE PC\n");
216e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("  ELF_FILE\n");
217e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("    The path to an elf file.\n");
218e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("  PC\n");
219e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("    The pc for which the register information should be obtained.\n");
220e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
221e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
222e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
223e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  struct stat st;
224e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (stat(argv[1], &st) == -1) {
225e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("Cannot stat %s: %s\n", argv[1], strerror(errno));
226e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
227e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
228e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (!S_ISREG(st.st_mode)) {
229e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("%s is not a regular file.\n", argv[1]);
230e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
231e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
232e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
233e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  uint64_t pc = 0;
234e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  char* end;
235e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  pc = strtoull(argv[2], &end, 16);
236e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  if (*end != '\0') {
237e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    printf("Malformed OFFSET value: %s\n", argv[2]);
238e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris    return 1;
239e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  }
240e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris
241e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris  return unwindstack::GetInfo(argv[1], pc);
242e37e2d05b1ae3f844750b76d3b71278b79d5de51Christopher Ferris}
243