1//===-- ProcessElfCore.h ----------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7// Notes about Linux Process core dumps:
8//  1) Linux core dump is stored as ELF file.
9//  2) The ELF file's PT_NOTE and PT_LOAD segments describes the program's
10//     address space and thread contexts.
11//  3) PT_NOTE segment contains note entries which describes a thread context.
12//  4) PT_LOAD segment describes a valid contiguous range of process address
13//     space.
14//===----------------------------------------------------------------------===//
15
16#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_PROCESSELFCORE_H
17#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_PROCESSELFCORE_H
18
19#include <list>
20#include <vector>
21
22#include "lldb/Target/PostMortemProcess.h"
23#include "lldb/Utility/Status.h"
24
25#include "Plugins/ObjectFile/ELF/ELFHeader.h"
26#include "Plugins/Process/elf-core/RegisterUtilities.h"
27
28struct ThreadData;
29
30class ProcessElfCore : public lldb_private::PostMortemProcess {
31public:
32  // Constructors and Destructors
33  static lldb::ProcessSP
34  CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
35                 const lldb_private::FileSpec *crash_file_path,
36                 bool can_connect);
37
38  static void Initialize();
39
40  static void Terminate();
41
42  static llvm::StringRef GetPluginNameStatic() { return "elf-core"; }
43
44  static llvm::StringRef GetPluginDescriptionStatic();
45
46  // Constructors and Destructors
47  ProcessElfCore(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
48                 const lldb_private::FileSpec &core_file);
49
50  ~ProcessElfCore() override;
51
52  // Check if a given Process
53  bool CanDebug(lldb::TargetSP target_sp,
54                bool plugin_specified_by_name) override;
55
56  // Creating a new process, or attaching to an existing one
57  lldb_private::Status DoLoadCore() override;
58
59  lldb_private::DynamicLoader *GetDynamicLoader() override;
60
61  // PluginInterface protocol
62  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
63
64  // Process Control
65  lldb_private::Status DoDestroy() override;
66
67  void RefreshStateAfterStop() override;
68
69  lldb_private::Status WillResume() override {
70    lldb_private::Status error;
71    error.SetErrorStringWithFormatv(
72        "error: {0} does not support resuming processes", GetPluginName());
73    return error;
74  }
75
76  // Process Queries
77  bool IsAlive() override;
78
79  bool WarnBeforeDetach() const override { return false; }
80
81  // Process Memory
82  size_t ReadMemory(lldb::addr_t addr, void *buf, size_t size,
83                    lldb_private::Status &error) override;
84
85  size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
86                      lldb_private::Status &error) override;
87
88  // We do not implement DoReadMemoryTags. Instead all the work is done in
89  // ReadMemoryTags which avoids having to unpack and repack tags.
90  llvm::Expected<std::vector<lldb::addr_t>> ReadMemoryTags(lldb::addr_t addr,
91                                                           size_t len) override;
92
93  lldb::addr_t GetImageInfoAddress() override;
94
95  lldb_private::ArchSpec GetArchitecture();
96
97  // Returns AUXV structure found in the core file
98  lldb_private::DataExtractor GetAuxvData() override;
99
100  bool GetProcessInfo(lldb_private::ProcessInstanceInfo &info) override;
101
102protected:
103  void Clear();
104
105  bool DoUpdateThreadList(lldb_private::ThreadList &old_thread_list,
106                          lldb_private::ThreadList &new_thread_list) override;
107
108  lldb_private::Status
109  DoGetMemoryRegionInfo(lldb::addr_t load_addr,
110                        lldb_private::MemoryRegionInfo &region_info) override;
111
112  bool SupportsMemoryTagging() override { return !m_core_tag_ranges.IsEmpty(); }
113
114private:
115  struct NT_FILE_Entry {
116    lldb::addr_t start;
117    lldb::addr_t end;
118    lldb::addr_t file_ofs;
119    std::string path;
120  };
121
122  // For ProcessElfCore only
123  typedef lldb_private::Range<lldb::addr_t, lldb::addr_t> FileRange;
124  typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, FileRange>
125      VMRangeToFileOffset;
126  typedef lldb_private::RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t>
127      VMRangeToPermissions;
128
129  lldb::ModuleSP m_core_module_sp;
130  lldb_private::FileSpec m_core_file;
131  std::string m_dyld_plugin_name;
132
133  // True if m_thread_contexts contains valid entries
134  bool m_thread_data_valid = false;
135
136  // Contain thread data read from NOTE segments
137  std::vector<ThreadData> m_thread_data;
138
139  // AUXV structure found from the NOTE segment
140  lldb_private::DataExtractor m_auxv;
141
142  // Address ranges found in the core
143  VMRangeToFileOffset m_core_aranges;
144
145  // Permissions for all ranges
146  VMRangeToPermissions m_core_range_infos;
147
148  // Memory tag ranges found in the core
149  VMRangeToFileOffset m_core_tag_ranges;
150
151  // NT_FILE entries found from the NOTE segment
152  std::vector<NT_FILE_Entry> m_nt_file_entries;
153
154  // Parse thread(s) data structures(prstatus, prpsinfo) from given NOTE segment
155  llvm::Error ParseThreadContextsFromNoteSegment(
156      const elf::ELFProgramHeader &segment_header,
157      const lldb_private::DataExtractor &segment_data);
158
159  // Returns number of thread contexts stored in the core file
160  uint32_t GetNumThreadContexts();
161
162  // Parse a contiguous address range of the process from LOAD segment
163  lldb::addr_t
164  AddAddressRangeFromLoadSegment(const elf::ELFProgramHeader &header);
165
166  // Parse a contiguous address range from a memory tag segment
167  lldb::addr_t
168  AddAddressRangeFromMemoryTagSegment(const elf::ELFProgramHeader &header);
169
170  llvm::Expected<std::vector<lldb_private::CoreNote>>
171  parseSegment(const lldb_private::DataExtractor &segment);
172  llvm::Error parseFreeBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
173  llvm::Error parseNetBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
174  llvm::Error parseOpenBSDNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
175  llvm::Error parseLinuxNotes(llvm::ArrayRef<lldb_private::CoreNote> notes);
176};
177
178#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_PROCESSELFCORE_H
179