1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2013 The Android Open Source Project
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
5bf215546Sopenharmony_ci * you may not use this file except in compliance with the License.
6bf215546Sopenharmony_ci * You may obtain a copy of the License at
7bf215546Sopenharmony_ci *
8bf215546Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
9bf215546Sopenharmony_ci *
10bf215546Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
11bf215546Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
12bf215546Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13bf215546Sopenharmony_ci * See the License for the specific language governing permissions and
14bf215546Sopenharmony_ci * limitations under the License.
15bf215546Sopenharmony_ci */
16bf215546Sopenharmony_ci
17bf215546Sopenharmony_ci#ifndef _BACKTRACE_BACKTRACE_H
18bf215546Sopenharmony_ci#define _BACKTRACE_BACKTRACE_H
19bf215546Sopenharmony_ci
20bf215546Sopenharmony_ci#include <inttypes.h>
21bf215546Sopenharmony_ci#include <stdint.h>
22bf215546Sopenharmony_ci
23bf215546Sopenharmony_ci#include <string>
24bf215546Sopenharmony_ci#include <vector>
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include <backtrace/backtrace_constants.h>
27bf215546Sopenharmony_ci#include <backtrace/BacktraceMap.h>
28bf215546Sopenharmony_ci
29bf215546Sopenharmony_ci#if defined(__LP64__)
30bf215546Sopenharmony_ci#define PRIPTR "016" PRIx64
31bf215546Sopenharmony_citypedef uint64_t word_t;
32bf215546Sopenharmony_ci#else
33bf215546Sopenharmony_ci#define PRIPTR "08" PRIx64
34bf215546Sopenharmony_citypedef uint32_t word_t;
35bf215546Sopenharmony_ci#endif
36bf215546Sopenharmony_ci
37bf215546Sopenharmony_cienum BacktraceUnwindErrorCode : uint32_t {
38bf215546Sopenharmony_ci  BACKTRACE_UNWIND_NO_ERROR,
39bf215546Sopenharmony_ci  // Something failed while trying to perform the setup to begin the unwind.
40bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_SETUP_FAILED,
41bf215546Sopenharmony_ci  // There is no map information to use with the unwind.
42bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_MAP_MISSING,
43bf215546Sopenharmony_ci  // An error occurred that indicates a programming error.
44bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_INTERNAL,
45bf215546Sopenharmony_ci  // The thread to unwind has disappeared before the unwind can begin.
46bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_THREAD_DOESNT_EXIST,
47bf215546Sopenharmony_ci  // The thread to unwind has not responded to a signal in a timely manner.
48bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_THREAD_TIMEOUT,
49bf215546Sopenharmony_ci  // Attempt to do an unsupported operation.
50bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_UNSUPPORTED_OPERATION,
51bf215546Sopenharmony_ci  // Attempt to do an offline unwind without a context.
52bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_NO_CONTEXT,
53bf215546Sopenharmony_ci  // The count of frames exceed MAX_BACKTRACE_FRAMES.
54bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_EXCEED_MAX_FRAMES_LIMIT,
55bf215546Sopenharmony_ci  // Failed to read memory.
56bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED,
57bf215546Sopenharmony_ci  // Failed to read registers.
58bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED,
59bf215546Sopenharmony_ci  // Failed to find a function in debug sections.
60bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_FIND_PROC_INFO_FAILED,
61bf215546Sopenharmony_ci  // Failed to execute dwarf instructions in debug sections.
62bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_EXECUTE_DWARF_INSTRUCTION_FAILED,
63bf215546Sopenharmony_ci  // Unwind information is incorrect.
64bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_UNWIND_INFO,
65bf215546Sopenharmony_ci  // Unwind information stopped due to sp/pc repeating.
66bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_REPEATED_FRAME,
67bf215546Sopenharmony_ci  // Unwind information stopped due to invalid elf.
68bf215546Sopenharmony_ci  BACKTRACE_UNWIND_ERROR_INVALID_ELF,
69bf215546Sopenharmony_ci};
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_cistruct BacktraceUnwindError {
72bf215546Sopenharmony_ci  enum BacktraceUnwindErrorCode error_code;
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci  union {
75bf215546Sopenharmony_ci    // for BACKTRACE_UNWIND_ERROR_ACCESS_MEM_FAILED
76bf215546Sopenharmony_ci    uint64_t addr;
77bf215546Sopenharmony_ci    // for BACKTRACE_UNWIND_ERROR_ACCESS_REG_FAILED
78bf215546Sopenharmony_ci    uint64_t regno;
79bf215546Sopenharmony_ci  } error_info;
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci  BacktraceUnwindError() : error_code(BACKTRACE_UNWIND_NO_ERROR) {}
82bf215546Sopenharmony_ci};
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_cistruct backtrace_frame_data_t {
85bf215546Sopenharmony_ci  size_t num;             // The current fame number.
86bf215546Sopenharmony_ci  uint64_t pc;            // The absolute pc.
87bf215546Sopenharmony_ci  uint64_t rel_pc;        // The relative pc.
88bf215546Sopenharmony_ci  uint64_t sp;            // The top of the stack.
89bf215546Sopenharmony_ci  size_t stack_size;      // The size of the stack, zero indicate an unknown stack size.
90bf215546Sopenharmony_ci  backtrace_map_t map;    // The map associated with the given pc.
91bf215546Sopenharmony_ci  std::string func_name;  // The function name associated with this pc, NULL if not found.
92bf215546Sopenharmony_ci  uint64_t func_offset;  // pc relative to the start of the function, only valid if func_name is not
93bf215546Sopenharmony_ci                         // NULL.
94bf215546Sopenharmony_ci};
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistruct backtrace_stackinfo_t {
97bf215546Sopenharmony_ci  uint64_t start;
98bf215546Sopenharmony_ci  uint64_t end;
99bf215546Sopenharmony_ci  const uint8_t* data;
100bf215546Sopenharmony_ci};
101bf215546Sopenharmony_ci
102bf215546Sopenharmony_cinamespace unwindstack {
103bf215546Sopenharmony_ciclass Regs;
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ciclass Backtrace {
107bf215546Sopenharmony_ci public:
108bf215546Sopenharmony_ci  enum ArchEnum : uint8_t {
109bf215546Sopenharmony_ci    ARCH_ARM,
110bf215546Sopenharmony_ci    ARCH_ARM64,
111bf215546Sopenharmony_ci    ARCH_X86,
112bf215546Sopenharmony_ci    ARCH_X86_64,
113bf215546Sopenharmony_ci  };
114bf215546Sopenharmony_ci
115bf215546Sopenharmony_ci  static void SetGlobalElfCache(bool enable);
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci  // Create the correct Backtrace object based on what is to be unwound.
118bf215546Sopenharmony_ci  // If pid < 0 or equals the current pid, then the Backtrace object
119bf215546Sopenharmony_ci  // corresponds to the current process.
120bf215546Sopenharmony_ci  // If pid < 0 or equals the current pid and tid >= 0, then the Backtrace
121bf215546Sopenharmony_ci  // object corresponds to a thread in the current process.
122bf215546Sopenharmony_ci  // If pid >= 0 and tid < 0, then the Backtrace object corresponds to a
123bf215546Sopenharmony_ci  // different process.
124bf215546Sopenharmony_ci  // Tracing a thread in a different process is not supported.
125bf215546Sopenharmony_ci  // If map is NULL, then create the map and manage it internally.
126bf215546Sopenharmony_ci  // If map is not NULL, the map is still owned by the caller.
127bf215546Sopenharmony_ci  static Backtrace* Create(pid_t pid, pid_t tid, BacktraceMap* map = nullptr);
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci  virtual ~Backtrace();
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci  // Get the current stack trace and store in the backtrace_ structure.
132bf215546Sopenharmony_ci  virtual bool Unwind(size_t num_ignore_frames, void* context = nullptr) = 0;
133bf215546Sopenharmony_ci
134bf215546Sopenharmony_ci  static bool Unwind(unwindstack::Regs* regs, BacktraceMap* back_map,
135bf215546Sopenharmony_ci                     std::vector<backtrace_frame_data_t>* frames, size_t num_ignore_frames,
136bf215546Sopenharmony_ci                     std::vector<std::string>* skip_names, BacktraceUnwindError* error = nullptr);
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci  // Get the function name and offset into the function given the pc.
139bf215546Sopenharmony_ci  // If the string is empty, then no valid function name was found,
140bf215546Sopenharmony_ci  // or the pc is not in any valid map.
141bf215546Sopenharmony_ci  virtual std::string GetFunctionName(uint64_t pc, uint64_t* offset,
142bf215546Sopenharmony_ci                                      const backtrace_map_t* map = nullptr);
143bf215546Sopenharmony_ci
144bf215546Sopenharmony_ci  // Fill in the map data associated with the given pc.
145bf215546Sopenharmony_ci  virtual void FillInMap(uint64_t pc, backtrace_map_t* map);
146bf215546Sopenharmony_ci
147bf215546Sopenharmony_ci  // Read the data at a specific address.
148bf215546Sopenharmony_ci  virtual bool ReadWord(uint64_t ptr, word_t* out_value) = 0;
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci  // Read arbitrary data from a specific address. If a read request would
151bf215546Sopenharmony_ci  // span from one map to another, this call only reads up until the end
152bf215546Sopenharmony_ci  // of the current map.
153bf215546Sopenharmony_ci  // Returns the total number of bytes actually read.
154bf215546Sopenharmony_ci  virtual size_t Read(uint64_t addr, uint8_t* buffer, size_t bytes) = 0;
155bf215546Sopenharmony_ci
156bf215546Sopenharmony_ci  // Create a string representing the formatted line of backtrace information
157bf215546Sopenharmony_ci  // for a single frame.
158bf215546Sopenharmony_ci  virtual std::string FormatFrameData(size_t frame_num);
159bf215546Sopenharmony_ci  static std::string FormatFrameData(const backtrace_frame_data_t* frame);
160bf215546Sopenharmony_ci
161bf215546Sopenharmony_ci  pid_t Pid() const { return pid_; }
162bf215546Sopenharmony_ci  pid_t Tid() const { return tid_; }
163bf215546Sopenharmony_ci  size_t NumFrames() const { return frames_.size(); }
164bf215546Sopenharmony_ci
165bf215546Sopenharmony_ci  const backtrace_frame_data_t* GetFrame(size_t frame_num) {
166bf215546Sopenharmony_ci    if (frame_num >= frames_.size()) {
167bf215546Sopenharmony_ci      return nullptr;
168bf215546Sopenharmony_ci    }
169bf215546Sopenharmony_ci    return &frames_[frame_num];
170bf215546Sopenharmony_ci  }
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci  typedef std::vector<backtrace_frame_data_t>::iterator iterator;
173bf215546Sopenharmony_ci  iterator begin() { return frames_.begin(); }
174bf215546Sopenharmony_ci  iterator end() { return frames_.end(); }
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci  typedef std::vector<backtrace_frame_data_t>::const_iterator const_iterator;
177bf215546Sopenharmony_ci  const_iterator begin() const { return frames_.begin(); }
178bf215546Sopenharmony_ci  const_iterator end() const { return frames_.end(); }
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci  BacktraceMap* GetMap() { return map_; }
181bf215546Sopenharmony_ci
182bf215546Sopenharmony_ci  BacktraceUnwindError GetError() { return error_; }
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci  std::string GetErrorString(BacktraceUnwindError error);
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci  // Set whether to skip frames in libbacktrace/libunwindstack when doing a local unwind.
187bf215546Sopenharmony_ci  void SetSkipFrames(bool skip_frames) { skip_frames_ = skip_frames; }
188bf215546Sopenharmony_ci
189bf215546Sopenharmony_ci protected:
190bf215546Sopenharmony_ci  Backtrace(pid_t pid, pid_t tid, BacktraceMap* map);
191bf215546Sopenharmony_ci
192bf215546Sopenharmony_ci  // The name returned is not demangled, GetFunctionName() takes care of
193bf215546Sopenharmony_ci  // demangling the name.
194bf215546Sopenharmony_ci  virtual std::string GetFunctionNameRaw(uint64_t pc, uint64_t* offset) = 0;
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci  virtual bool VerifyReadWordArgs(uint64_t ptr, word_t* out_value);
197bf215546Sopenharmony_ci
198bf215546Sopenharmony_ci  bool BuildMap();
199bf215546Sopenharmony_ci
200bf215546Sopenharmony_ci  pid_t pid_;
201bf215546Sopenharmony_ci  pid_t tid_;
202bf215546Sopenharmony_ci
203bf215546Sopenharmony_ci  BacktraceMap* map_;
204bf215546Sopenharmony_ci  bool map_shared_;
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci  std::vector<backtrace_frame_data_t> frames_;
207bf215546Sopenharmony_ci
208bf215546Sopenharmony_ci  // Skip frames in libbacktrace/libunwindstack when doing a local unwind.
209bf215546Sopenharmony_ci  bool skip_frames_ = true;
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci  BacktraceUnwindError error_;
212bf215546Sopenharmony_ci};
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci#endif // _BACKTRACE_BACKTRACE_H
215