Coverage Report

Created: 2023-11-11 10:31

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- ProcessElfCore.cpp ------------------------------------------------===//
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
//===----------------------------------------------------------------------===//
8
9
#include <cstdlib>
10
11
#include <memory>
12
#include <mutex>
13
14
#include "lldb/Core/Module.h"
15
#include "lldb/Core/ModuleSpec.h"
16
#include "lldb/Core/PluginManager.h"
17
#include "lldb/Core/Section.h"
18
#include "lldb/Target/ABI.h"
19
#include "lldb/Target/DynamicLoader.h"
20
#include "lldb/Target/MemoryRegionInfo.h"
21
#include "lldb/Target/Target.h"
22
#include "lldb/Target/UnixSignals.h"
23
#include "lldb/Utility/DataBufferHeap.h"
24
#include "lldb/Utility/LLDBLog.h"
25
#include "lldb/Utility/Log.h"
26
#include "lldb/Utility/State.h"
27
28
#include "llvm/BinaryFormat/ELF.h"
29
#include "llvm/Support/Threading.h"
30
31
#include "Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.h"
32
#include "Plugins/ObjectFile/ELF/ObjectFileELF.h"
33
#include "Plugins/Process/elf-core/RegisterUtilities.h"
34
#include "ProcessElfCore.h"
35
#include "ThreadElfCore.h"
36
37
using namespace lldb_private;
38
namespace ELF = llvm::ELF;
39
40
LLDB_PLUGIN_DEFINE(ProcessElfCore)
41
42
3.95k
llvm::StringRef ProcessElfCore::GetPluginDescriptionStatic() {
43
3.95k
  return "ELF core dump plug-in.";
44
3.95k
}
45
46
3.94k
void ProcessElfCore::Terminate() {
47
3.94k
  PluginManager::UnregisterPlugin(ProcessElfCore::CreateInstance);
48
3.94k
}
49
50
lldb::ProcessSP ProcessElfCore::CreateInstance(lldb::TargetSP target_sp,
51
                                               lldb::ListenerSP listener_sp,
52
                                               const FileSpec *crash_file,
53
197
                                               bool can_connect) {
54
197
  lldb::ProcessSP process_sp;
55
197
  if (crash_file && 
!can_connect190
) {
56
    // Read enough data for an ELF32 header or ELF64 header Note: Here we care
57
    // about e_type field only, so it is safe to ignore possible presence of
58
    // the header extension.
59
190
    const size_t header_size = sizeof(llvm::ELF::Elf64_Ehdr);
60
61
190
    auto data_sp = FileSystem::Instance().CreateDataBuffer(
62
190
        crash_file->GetPath(), header_size, 0);
63
190
    if (data_sp && 
data_sp->GetByteSize() == header_size189
&&
64
190
        
elf::ELFHeader::MagicBytesMatch(data_sp->GetBytes())189
) {
65
66
      elf::ELFHeader elf_header;
66
66
      DataExtractor data(data_sp, lldb::eByteOrderLittle, 4);
67
66
      lldb::offset_t data_offset = 0;
68
66
      if (elf_header.Parse(data, &data_offset)) {
69
        // Check whether we're dealing with a raw FreeBSD "full memory dump"
70
        // ELF vmcore that needs to be handled via FreeBSDKernel plugin instead.
71
66
        if (elf_header.e_ident[7] == 0xFF && 
elf_header.e_version == 00
)
72
0
          return process_sp;
73
66
        if (elf_header.e_type == llvm::ELF::ET_CORE)
74
66
          process_sp = std::make_shared<ProcessElfCore>(target_sp, listener_sp,
75
66
                                                        *crash_file);
76
66
      }
77
66
    }
78
190
  }
79
197
  return process_sp;
80
197
}
81
82
bool ProcessElfCore::CanDebug(lldb::TargetSP target_sp,
83
66
                              bool plugin_specified_by_name) {
84
  // For now we are just making sure the file exists for a given module
85
66
  if (!m_core_module_sp && FileSystem::Instance().Exists(m_core_file)) {
86
66
    ModuleSpec core_module_spec(m_core_file, target_sp->GetArchitecture());
87
66
    Status error(ModuleList::GetSharedModule(core_module_spec, m_core_module_sp,
88
66
                                             nullptr, nullptr, nullptr));
89
66
    if (m_core_module_sp) {
90
66
      ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
91
66
      if (core_objfile && core_objfile->GetType() == ObjectFile::eTypeCoreFile)
92
66
        return true;
93
66
    }
94
66
  }
95
0
  return false;
96
66
}
97
98
// ProcessElfCore constructor
99
ProcessElfCore::ProcessElfCore(lldb::TargetSP target_sp,
100
                               lldb::ListenerSP listener_sp,
101
                               const FileSpec &core_file)
102
66
    : PostMortemProcess(target_sp, listener_sp), m_core_file(core_file) {}
103
104
// Destructor
105
66
ProcessElfCore::~ProcessElfCore() {
106
66
  Clear();
107
  // We need to call finalize on the process before destroying ourselves to
108
  // make sure all of the broadcaster cleanup goes as planned. If we destruct
109
  // this class, then Process::~Process() might have problems trying to fully
110
  // destroy the broadcaster.
111
66
  Finalize();
112
66
}
113
114
lldb::addr_t ProcessElfCore::AddAddressRangeFromLoadSegment(
115
1.50k
    const elf::ELFProgramHeader &header) {
116
1.50k
  const lldb::addr_t addr = header.p_vaddr;
117
1.50k
  FileRange file_range(header.p_offset, header.p_filesz);
118
1.50k
  VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);
119
120
  // Only add to m_core_aranges if the file size is non zero. Some core files
121
  // have PT_LOAD segments for all address ranges, but set f_filesz to zero for
122
  // the .text sections since they can be retrieved from the object files.
123
1.50k
  if (header.p_filesz > 0) {
124
873
    VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
125
873
    if (last_entry && 
last_entry->GetRangeEnd() == range_entry.GetRangeBase()808
&&
126
873
        
last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase()436
&&
127
873
        
last_entry->GetByteSize() == last_entry->data.GetByteSize()436
) {
128
318
      last_entry->SetRangeEnd(range_entry.GetRangeEnd());
129
318
      last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
130
555
    } else {
131
555
      m_core_aranges.Append(range_entry);
132
555
    }
133
873
  }
134
  // Keep a separate map of permissions that isn't coalesced so all ranges
135
  // are maintained.
136
1.50k
  const uint32_t permissions =
137
1.50k
      ((header.p_flags & llvm::ELF::PF_R) ? 
lldb::ePermissionsReadable1.40k
:
0u94
) |
138
1.50k
      ((header.p_flags & llvm::ELF::PF_W) ? 
lldb::ePermissionsWritable775
:
0u725
) |
139
1.50k
      ((header.p_flags & llvm::ELF::PF_X) ? 
lldb::ePermissionsExecutable264
:
0u1.23k
);
140
141
1.50k
  m_core_range_infos.Append(
142
1.50k
      VMRangeToPermissions::Entry(addr, header.p_memsz, permissions));
143
144
1.50k
  return addr;
145
1.50k
}
146
147
lldb::addr_t ProcessElfCore::AddAddressRangeFromMemoryTagSegment(
148
5
    const elf::ELFProgramHeader &header) {
149
  // If lldb understood multiple kinds of tag segments we would record the type
150
  // of the segment here also. As long as there is only 1 type lldb looks for,
151
  // there is no need.
152
5
  FileRange file_range(header.p_offset, header.p_filesz);
153
5
  m_core_tag_ranges.Append(
154
5
      VMRangeToFileOffset::Entry(header.p_vaddr, header.p_memsz, file_range));
155
156
5
  return header.p_vaddr;
157
5
}
158
159
// Process Control
160
66
Status ProcessElfCore::DoLoadCore() {
161
66
  Status error;
162
66
  if (!m_core_module_sp) {
163
0
    error.SetErrorString("invalid core module");
164
0
    return error;
165
0
  }
166
167
66
  ObjectFileELF *core = (ObjectFileELF *)(m_core_module_sp->GetObjectFile());
168
66
  if (core == nullptr) {
169
0
    error.SetErrorString("invalid core object file");
170
0
    return error;
171
0
  }
172
173
66
  llvm::ArrayRef<elf::ELFProgramHeader> segments = core->ProgramHeaders();
174
66
  if (segments.size() == 0) {
175
0
    error.SetErrorString("core file has no segments");
176
0
    return error;
177
0
  }
178
179
66
  SetCanJIT(false);
180
181
66
  m_thread_data_valid = true;
182
183
66
  bool ranges_are_sorted = true;
184
66
  lldb::addr_t vm_addr = 0;
185
66
  lldb::addr_t tag_addr = 0;
186
  /// Walk through segments and Thread and Address Map information.
187
  /// PT_NOTE - Contains Thread and Register information
188
  /// PT_LOAD - Contains a contiguous range of Process Address Space
189
  /// PT_AARCH64_MEMTAG_MTE - Contains AArch64 MTE memory tags for a range of
190
  ///                         Process Address Space.
191
1.57k
  for (const elf::ELFProgramHeader &H : segments) {
192
1.57k
    DataExtractor data = core->GetSegmentData(H);
193
194
    // Parse thread contexts and auxv structure
195
1.57k
    if (H.p_type == llvm::ELF::PT_NOTE) {
196
66
      if (llvm::Error error = ParseThreadContextsFromNoteSegment(H, data))
197
0
        return Status(std::move(error));
198
66
    }
199
    // PT_LOAD segments contains address map
200
1.57k
    if (H.p_type == llvm::ELF::PT_LOAD) {
201
1.50k
      lldb::addr_t last_addr = AddAddressRangeFromLoadSegment(H);
202
1.50k
      if (vm_addr > last_addr)
203
0
        ranges_are_sorted = false;
204
1.50k
      vm_addr = last_addr;
205
1.50k
    } else 
if (71
H.p_type == llvm::ELF::PT_AARCH64_MEMTAG_MTE71
) {
206
5
      lldb::addr_t last_addr = AddAddressRangeFromMemoryTagSegment(H);
207
5
      if (tag_addr > last_addr)
208
0
        ranges_are_sorted = false;
209
5
      tag_addr = last_addr;
210
5
    }
211
1.57k
  }
212
213
66
  if (!ranges_are_sorted) {
214
0
    m_core_aranges.Sort();
215
0
    m_core_range_infos.Sort();
216
0
    m_core_tag_ranges.Sort();
217
0
  }
218
219
  // Even if the architecture is set in the target, we need to override it to
220
  // match the core file which is always single arch.
221
66
  ArchSpec arch(m_core_module_sp->GetArchitecture());
222
223
66
  ArchSpec target_arch = GetTarget().GetArchitecture();
224
66
  ArchSpec core_arch(m_core_module_sp->GetArchitecture());
225
66
  target_arch.MergeFrom(core_arch);
226
66
  GetTarget().SetArchitecture(target_arch);
227
 
228
66
  SetUnixSignals(UnixSignals::Create(GetArchitecture()));
229
230
  // Ensure we found at least one thread that was stopped on a signal.
231
66
  bool siginfo_signal_found = false;
232
66
  bool prstatus_signal_found = false;
233
  // Check we found a signal in a SIGINFO note.
234
101
  for (const auto &thread_data : m_thread_data) {
235
101
    if (thread_data.signo != 0)
236
80
      siginfo_signal_found = true;
237
101
    if (thread_data.prstatus_sig != 0)
238
54
      prstatus_signal_found = true;
239
101
  }
240
66
  if (!siginfo_signal_found) {
241
    // If we don't have signal from SIGINFO use the signal from each threads
242
    // PRSTATUS note.
243
1
    if (prstatus_signal_found) {
244
1
      for (auto &thread_data : m_thread_data)
245
1
        thread_data.signo = thread_data.prstatus_sig;
246
1
    } else 
if (0
m_thread_data.size() > 00
) {
247
      // If all else fails force the first thread to be SIGSTOP
248
0
      m_thread_data.begin()->signo =
249
0
          GetUnixSignals()->GetSignalNumberFromName("SIGSTOP");
250
0
    }
251
1
  }
252
253
  // Core files are useless without the main executable. See if we can locate
254
  // the main executable using data we found in the core file notes.
255
66
  lldb::ModuleSP exe_module_sp = GetTarget().GetExecutableModule();
256
66
  if (!exe_module_sp) {
257
    // The first entry in the NT_FILE might be our executable
258
50
    if (!m_nt_file_entries.empty()) {
259
31
      ModuleSpec exe_module_spec;
260
31
      exe_module_spec.GetArchitecture() = arch;
261
31
      exe_module_spec.GetFileSpec().SetFile(m_nt_file_entries[0].path,
262
31
                                            FileSpec::Style::native);
263
31
      if (exe_module_spec.GetFileSpec()) {
264
31
        exe_module_sp = GetTarget().GetOrCreateModule(exe_module_spec, 
265
31
                                                      true /* notify */);
266
31
        if (exe_module_sp)
267
2
          GetTarget().SetExecutableModule(exe_module_sp, eLoadDependentsNo);
268
31
      }
269
31
    }
270
50
  }
271
66
  return error;
272
66
}
273
274
162
lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader() {
275
162
  if (m_dyld_up.get() == nullptr)
276
66
    m_dyld_up.reset(DynamicLoader::FindPlugin(
277
66
        this, DynamicLoaderPOSIXDYLD::GetPluginNameStatic()));
278
162
  return m_dyld_up.get();
279
162
}
280
281
bool ProcessElfCore::DoUpdateThreadList(ThreadList &old_thread_list,
282
66
                                        ThreadList &new_thread_list) {
283
66
  const uint32_t num_threads = GetNumThreadContexts();
284
66
  if (!m_thread_data_valid)
285
0
    return false;
286
287
167
  
for (lldb::tid_t tid = 0; 66
tid < num_threads;
++tid101
) {
288
101
    const ThreadData &td = m_thread_data[tid];
289
101
    lldb::ThreadSP thread_sp(new ThreadElfCore(*this, td));
290
101
    new_thread_list.AddThread(thread_sp);
291
101
  }
292
66
  return new_thread_list.GetSize(false) > 0;
293
66
}
294
295
66
void ProcessElfCore::RefreshStateAfterStop() {}
296
297
129
Status ProcessElfCore::DoDestroy() { return Status(); }
298
299
// Process Queries
300
301
513
bool ProcessElfCore::IsAlive() { return true; }
302
303
// Process Memory
304
size_t ProcessElfCore::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
305
665
                                  Status &error) {
306
665
  if (lldb::ABISP abi_sp = GetABI())
307
665
    addr = abi_sp->FixAnyAddress(addr);
308
309
  // Don't allow the caching that lldb_private::Process::ReadMemory does since
310
  // in core files we have it all cached our our core file anyway.
311
665
  return DoReadMemory(addr, buf, size, error);
312
665
}
313
314
Status ProcessElfCore::DoGetMemoryRegionInfo(lldb::addr_t load_addr,
315
1.66k
                                             MemoryRegionInfo &region_info) {
316
1.66k
  region_info.Clear();
317
1.66k
  const VMRangeToPermissions::Entry *permission_entry =
318
1.66k
      m_core_range_infos.FindEntryThatContainsOrFollows(load_addr);
319
1.66k
  if (permission_entry) {
320
1.60k
    if (permission_entry->Contains(load_addr)) {
321
1.31k
      region_info.GetRange().SetRangeBase(permission_entry->GetRangeBase());
322
1.31k
      region_info.GetRange().SetRangeEnd(permission_entry->GetRangeEnd());
323
1.31k
      const Flags permissions(permission_entry->data);
324
1.31k
      region_info.SetReadable(permissions.Test(lldb::ePermissionsReadable)
325
1.31k
                                  ? 
MemoryRegionInfo::eYes1.21k
326
1.31k
                                  : 
MemoryRegionInfo::eNo102
);
327
1.31k
      region_info.SetWritable(permissions.Test(lldb::ePermissionsWritable)
328
1.31k
                                  ? 
MemoryRegionInfo::eYes767
329
1.31k
                                  : 
MemoryRegionInfo::eNo545
);
330
1.31k
      region_info.SetExecutable(permissions.Test(lldb::ePermissionsExecutable)
331
1.31k
                                    ? 
MemoryRegionInfo::eYes319
332
1.31k
                                    : 
MemoryRegionInfo::eNo993
);
333
1.31k
      region_info.SetMapped(MemoryRegionInfo::eYes);
334
335
      // A region is memory tagged if there is a memory tag segment that covers
336
      // the exact same range.
337
1.31k
      region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
338
1.31k
      const VMRangeToFileOffset::Entry *tag_entry =
339
1.31k
          m_core_tag_ranges.FindEntryStartsAt(permission_entry->GetRangeBase());
340
1.31k
      if (tag_entry &&
341
1.31k
          
tag_entry->GetRangeEnd() == permission_entry->GetRangeEnd()16
)
342
16
        region_info.SetMemoryTagged(MemoryRegionInfo::eYes);
343
1.31k
    } else 
if (291
load_addr < permission_entry->GetRangeBase()291
) {
344
291
      region_info.GetRange().SetRangeBase(load_addr);
345
291
      region_info.GetRange().SetRangeEnd(permission_entry->GetRangeBase());
346
291
      region_info.SetReadable(MemoryRegionInfo::eNo);
347
291
      region_info.SetWritable(MemoryRegionInfo::eNo);
348
291
      region_info.SetExecutable(MemoryRegionInfo::eNo);
349
291
      region_info.SetMapped(MemoryRegionInfo::eNo);
350
291
      region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
351
291
    }
352
1.60k
    return Status();
353
1.60k
  }
354
355
60
  region_info.GetRange().SetRangeBase(load_addr);
356
60
  region_info.GetRange().SetRangeEnd(LLDB_INVALID_ADDRESS);
357
60
  region_info.SetReadable(MemoryRegionInfo::eNo);
358
60
  region_info.SetWritable(MemoryRegionInfo::eNo);
359
60
  region_info.SetExecutable(MemoryRegionInfo::eNo);
360
60
  region_info.SetMapped(MemoryRegionInfo::eNo);
361
60
  region_info.SetMemoryTagged(MemoryRegionInfo::eNo);
362
60
  return Status();
363
1.66k
}
364
365
size_t ProcessElfCore::DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
366
665
                                    Status &error) {
367
665
  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
368
369
665
  if (core_objfile == nullptr)
370
0
    return 0;
371
372
  // Get the address range
373
665
  const VMRangeToFileOffset::Entry *address_range =
374
665
      m_core_aranges.FindEntryThatContains(addr);
375
665
  if (address_range == nullptr || 
address_range->GetRangeEnd() < addr600
) {
376
65
    error.SetErrorStringWithFormat("core file does not contain 0x%" PRIx64,
377
65
                                   addr);
378
65
    return 0;
379
65
  }
380
381
  // Convert the address into core file offset
382
600
  const lldb::addr_t offset = addr - address_range->GetRangeBase();
383
600
  const lldb::addr_t file_start = address_range->data.GetRangeBase();
384
600
  const lldb::addr_t file_end = address_range->data.GetRangeEnd();
385
600
  size_t bytes_to_read = size; // Number of bytes to read from the core file
386
600
  size_t bytes_copied = 0;   // Number of bytes actually read from the core file
387
600
  lldb::addr_t bytes_left =
388
600
      0; // Number of bytes available in the core file from the given address
389
390
  // Don't proceed if core file doesn't contain the actual data for this
391
  // address range.
392
600
  if (file_start == file_end)
393
0
    return 0;
394
395
  // Figure out how many on-disk bytes remain in this segment starting at the
396
  // given offset
397
600
  if (file_end > file_start + offset)
398
600
    bytes_left = file_end - (file_start + offset);
399
400
600
  if (bytes_to_read > bytes_left)
401
1
    bytes_to_read = bytes_left;
402
403
  // If there is data available on the core file read it
404
600
  if (bytes_to_read)
405
600
    bytes_copied =
406
600
        core_objfile->CopyData(offset + file_start, bytes_to_read, buf);
407
408
600
  return bytes_copied;
409
600
}
410
411
llvm::Expected<std::vector<lldb::addr_t>>
412
9
ProcessElfCore::ReadMemoryTags(lldb::addr_t addr, size_t len) {
413
9
  ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
414
9
  if (core_objfile == nullptr)
415
0
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
416
0
                                   "No core object file.");
417
418
9
  llvm::Expected<const MemoryTagManager *> tag_manager_or_err =
419
9
      GetMemoryTagManager();
420
9
  if (!tag_manager_or_err)
421
0
    return tag_manager_or_err.takeError();
422
423
  // LLDB only supports AArch64 MTE tag segments so we do not need to worry
424
  // about the segment type here. If you got here then you must have a tag
425
  // manager (meaning you are debugging AArch64) and all the segments in this
426
  // list will have had type PT_AARCH64_MEMTAG_MTE.
427
9
  const VMRangeToFileOffset::Entry *tag_entry =
428
9
      m_core_tag_ranges.FindEntryThatContains(addr);
429
  // If we don't have a tag segment or the range asked for extends outside the
430
  // segment.
431
9
  if (!tag_entry || (addr + len) >= tag_entry->GetRangeEnd())
432
0
    return llvm::createStringError(llvm::inconvertibleErrorCode(),
433
0
                                   "No tag segment that covers this range.");
434
435
9
  const MemoryTagManager *tag_manager = *tag_manager_or_err;
436
9
  return tag_manager->UnpackTagsFromCoreFileSegment(
437
9
      [core_objfile](lldb::offset_t offset, size_t length, void *dst) {
438
9
        return core_objfile->CopyData(offset, length, dst);
439
9
      },
440
9
      tag_entry->GetRangeBase(), tag_entry->data.GetRangeBase(), addr, len);
441
9
}
442
443
66
void ProcessElfCore::Clear() {
444
66
  m_thread_list.Clear();
445
446
66
  SetUnixSignals(std::make_shared<UnixSignals>());
447
66
}
448
449
3.95k
void ProcessElfCore::Initialize() {
450
3.95k
  static llvm::once_flag g_once_flag;
451
452
3.95k
  llvm::call_once(g_once_flag, []() {
453
3.95k
    PluginManager::RegisterPlugin(GetPluginNameStatic(),
454
3.95k
                                  GetPluginDescriptionStatic(), CreateInstance);
455
3.95k
  });
456
3.95k
}
457
458
18
lldb::addr_t ProcessElfCore::GetImageInfoAddress() {
459
18
  ObjectFile *obj_file = GetTarget().GetExecutableModule()->GetObjectFile();
460
18
  Address addr = obj_file->GetImageInfoAddress(&GetTarget());
461
462
18
  if (addr.IsValid())
463
6
    return addr.GetLoadAddress(&GetTarget());
464
12
  return LLDB_INVALID_ADDRESS;
465
18
}
466
467
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details.
468
static void ParseFreeBSDPrStatus(ThreadData &thread_data,
469
                                 const DataExtractor &data,
470
18
                                 bool lp64) {
471
18
  lldb::offset_t offset = 0;
472
18
  int pr_version = data.GetU32(&offset);
473
474
18
  Log *log = GetLog(LLDBLog::Process);
475
18
  if (log) {
476
0
    if (pr_version > 1)
477
0
      LLDB_LOGF(log, "FreeBSD PRSTATUS unexpected version %d", pr_version);
478
0
  }
479
480
  // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate
481
18
  if (lp64)
482
11
    offset += 32;
483
7
  else
484
7
    offset += 16;
485
486
18
  thread_data.signo = data.GetU32(&offset); // pr_cursig
487
18
  thread_data.tid = data.GetU32(&offset);   // pr_pid
488
18
  if (lp64)
489
11
    offset += 4;
490
491
18
  size_t len = data.GetByteSize() - offset;
492
18
  thread_data.gpregset = DataExtractor(data, offset, len);
493
18
}
494
495
// Parse a FreeBSD NT_PRPSINFO note - see FreeBSD sys/procfs.h for details.
496
static void ParseFreeBSDPrPsInfo(ProcessElfCore &process,
497
                                 const DataExtractor &data,
498
9
                                 bool lp64) {
499
9
  lldb::offset_t offset = 0;
500
9
  int pr_version = data.GetU32(&offset);
501
502
9
  Log *log = GetLog(LLDBLog::Process);
503
9
  if (log) {
504
0
    if (pr_version > 1)
505
0
      LLDB_LOGF(log, "FreeBSD PRPSINFO unexpected version %d", pr_version);
506
0
  }
507
508
  // Skip pr_psinfosz, pr_fname, pr_psargs
509
9
  offset += 108;
510
9
  if (lp64)
511
5
    offset += 4;
512
513
9
  process.SetID(data.GetU32(&offset)); // pr_pid
514
9
}
515
516
static llvm::Error ParseNetBSDProcInfo(const DataExtractor &data,
517
                                       uint32_t &cpi_nlwps,
518
                                       uint32_t &cpi_signo,
519
                                       uint32_t &cpi_siglwp,
520
13
                                       uint32_t &cpi_pid) {
521
13
  lldb::offset_t offset = 0;
522
523
13
  uint32_t version = data.GetU32(&offset);
524
13
  if (version != 1)
525
0
    return llvm::make_error<llvm::StringError>(
526
0
        "Error parsing NetBSD core(5) notes: Unsupported procinfo version",
527
0
        llvm::inconvertibleErrorCode());
528
529
13
  uint32_t cpisize = data.GetU32(&offset);
530
13
  if (cpisize != NETBSD::NT_PROCINFO_SIZE)
531
0
    return llvm::make_error<llvm::StringError>(
532
0
        "Error parsing NetBSD core(5) notes: Unsupported procinfo size",
533
0
        llvm::inconvertibleErrorCode());
534
535
13
  cpi_signo = data.GetU32(&offset); /* killing signal */
536
537
13
  offset += NETBSD::NT_PROCINFO_CPI_SIGCODE_SIZE;
538
13
  offset += NETBSD::NT_PROCINFO_CPI_SIGPEND_SIZE;
539
13
  offset += NETBSD::NT_PROCINFO_CPI_SIGMASK_SIZE;
540
13
  offset += NETBSD::NT_PROCINFO_CPI_SIGIGNORE_SIZE;
541
13
  offset += NETBSD::NT_PROCINFO_CPI_SIGCATCH_SIZE;
542
13
  cpi_pid = data.GetU32(&offset);
543
13
  offset += NETBSD::NT_PROCINFO_CPI_PPID_SIZE;
544
13
  offset += NETBSD::NT_PROCINFO_CPI_PGRP_SIZE;
545
13
  offset += NETBSD::NT_PROCINFO_CPI_SID_SIZE;
546
13
  offset += NETBSD::NT_PROCINFO_CPI_RUID_SIZE;
547
13
  offset += NETBSD::NT_PROCINFO_CPI_EUID_SIZE;
548
13
  offset += NETBSD::NT_PROCINFO_CPI_SVUID_SIZE;
549
13
  offset += NETBSD::NT_PROCINFO_CPI_RGID_SIZE;
550
13
  offset += NETBSD::NT_PROCINFO_CPI_EGID_SIZE;
551
13
  offset += NETBSD::NT_PROCINFO_CPI_SVGID_SIZE;
552
13
  cpi_nlwps = data.GetU32(&offset); /* number of LWPs */
553
554
13
  offset += NETBSD::NT_PROCINFO_CPI_NAME_SIZE;
555
13
  cpi_siglwp = data.GetU32(&offset); /* LWP target of killing signal */
556
557
13
  return llvm::Error::success();
558
13
}
559
560
static void ParseOpenBSDProcInfo(ThreadData &thread_data,
561
0
                                 const DataExtractor &data) {
562
0
  lldb::offset_t offset = 0;
563
564
0
  int version = data.GetU32(&offset);
565
0
  if (version != 1)
566
0
    return;
567
568
0
  offset += 4;
569
0
  thread_data.signo = data.GetU32(&offset);
570
0
}
571
572
llvm::Expected<std::vector<CoreNote>>
573
66
ProcessElfCore::parseSegment(const DataExtractor &segment) {
574
66
  lldb::offset_t offset = 0;
575
66
  std::vector<CoreNote> result;
576
577
811
  while (offset < segment.GetByteSize()) {
578
745
    ELFNote note = ELFNote();
579
745
    if (!note.Parse(segment, &offset))
580
0
      return llvm::make_error<llvm::StringError>(
581
0
          "Unable to parse note segment", llvm::inconvertibleErrorCode());
582
583
745
    size_t note_start = offset;
584
745
    size_t note_size = llvm::alignTo(note.n_descsz, 4);
585
586
745
    result.push_back({note, DataExtractor(segment, note_start, note_size)});
587
745
    offset += note_size;
588
745
  }
589
590
66
  return std::move(result);
591
66
}
592
593
9
llvm::Error ProcessElfCore::parseFreeBSDNotes(llvm::ArrayRef<CoreNote> notes) {
594
9
  ArchSpec arch = GetArchitecture();
595
9
  bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 ||
596
9
               
arch.GetMachine() == llvm::Triple::mips648
||
597
9
               
arch.GetMachine() == llvm::Triple::ppc648
||
598
9
               
arch.GetMachine() == llvm::Triple::x86_648
);
599
9
  bool have_prstatus = false;
600
9
  bool have_prpsinfo = false;
601
9
  ThreadData thread_data;
602
176
  for (const auto &note : notes) {
603
176
    if (note.info.n_name != "FreeBSD")
604
0
      continue;
605
606
176
    if ((note.info.n_type == ELF::NT_PRSTATUS && 
have_prstatus18
) ||
607
176
        
(167
note.info.n_type == ELF::NT_PRPSINFO167
&&
have_prpsinfo9
)) {
608
9
      assert(thread_data.gpregset.GetByteSize() > 0);
609
      // Add the new thread to thread list
610
9
      m_thread_data.push_back(thread_data);
611
9
      thread_data = ThreadData();
612
9
      have_prstatus = false;
613
9
      have_prpsinfo = false;
614
9
    }
615
616
176
    switch (note.info.n_type) {
617
18
    case ELF::NT_PRSTATUS:
618
18
      have_prstatus = true;
619
18
      ParseFreeBSDPrStatus(thread_data, note.data, lp64);
620
18
      break;
621
9
    case ELF::NT_PRPSINFO:
622
9
      have_prpsinfo = true;
623
9
      ParseFreeBSDPrPsInfo(*this, note.data, lp64);
624
9
      break;
625
18
    case ELF::NT_FREEBSD_THRMISC: {
626
18
      lldb::offset_t offset = 0;
627
18
      thread_data.name = note.data.GetCStr(&offset, 20);
628
18
      break;
629
0
    }
630
9
    case ELF::NT_FREEBSD_PROCSTAT_AUXV:
631
      // FIXME: FreeBSD sticks an int at the beginning of the note
632
9
      m_auxv = DataExtractor(note.data, 4, note.data.GetByteSize() - 4);
633
9
      break;
634
122
    default:
635
122
      thread_data.notes.push_back(note);
636
122
      break;
637
176
    }
638
176
  }
639
9
  if (!have_prstatus) {
640
0
    return llvm::make_error<llvm::StringError>(
641
0
        "Could not find NT_PRSTATUS note in core file.",
642
0
        llvm::inconvertibleErrorCode());
643
0
  }
644
9
  m_thread_data.push_back(thread_data);
645
9
  return llvm::Error::success();
646
9
}
647
648
/// NetBSD specific Thread context from PT_NOTE segment
649
///
650
/// NetBSD ELF core files use notes to provide information about
651
/// the process's state.  The note name is "NetBSD-CORE" for
652
/// information that is global to the process, and "NetBSD-CORE@nn",
653
/// where "nn" is the lwpid of the LWP that the information belongs
654
/// to (such as register state).
655
///
656
/// NetBSD uses the following note identifiers:
657
///
658
///      ELF_NOTE_NETBSD_CORE_PROCINFO (value 1)
659
///             Note is a "netbsd_elfcore_procinfo" structure.
660
///      ELF_NOTE_NETBSD_CORE_AUXV     (value 2; since NetBSD 8.0)
661
///             Note is an array of AuxInfo structures.
662
///
663
/// NetBSD also uses ptrace(2) request numbers (the ones that exist in
664
/// machine-dependent space) to identify register info notes.  The
665
/// info in such notes is in the same format that ptrace(2) would
666
/// export that information.
667
///
668
/// For more information see /usr/include/sys/exec_elf.h
669
///
670
13
llvm::Error ProcessElfCore::parseNetBSDNotes(llvm::ArrayRef<CoreNote> notes) {
671
13
  ThreadData thread_data;
672
13
  bool had_nt_regs = false;
673
674
  // To be extracted from struct netbsd_elfcore_procinfo
675
  // Used to sanity check of the LWPs of the process
676
13
  uint32_t nlwps = 0;
677
13
  uint32_t signo = 0;  // killing signal
678
13
  uint32_t siglwp = 0; // LWP target of killing signal
679
13
  uint32_t pr_pid = 0;
680
681
72
  for (const auto &note : notes) {
682
72
    llvm::StringRef name = note.info.n_name;
683
684
72
    if (name == "NetBSD-CORE") {
685
26
      if (note.info.n_type == NETBSD::NT_PROCINFO) {
686
13
        llvm::Error error = ParseNetBSDProcInfo(note.data, nlwps, signo,
687
13
                                                siglwp, pr_pid);
688
13
        if (error)
689
0
          return error;
690
13
        SetID(pr_pid);
691
13
      } else if (note.info.n_type == NETBSD::NT_AUXV) {
692
13
        m_auxv = note.data;
693
13
      }
694
46
    } else if (name.consume_front("NetBSD-CORE@")) {
695
46
      lldb::tid_t tid;
696
46
      if (name.getAsInteger(10, tid))
697
0
        return llvm::make_error<llvm::StringError>(
698
0
            "Error parsing NetBSD core(5) notes: Cannot convert LWP ID "
699
0
            "to integer",
700
0
            llvm::inconvertibleErrorCode());
701
702
46
      switch (GetArchitecture().GetMachine()) {
703
10
      case llvm::Triple::aarch64: {
704
        // Assume order PT_GETREGS, PT_GETFPREGS
705
10
        if (note.info.n_type == NETBSD::AARCH64::NT_REGS) {
706
          // If this is the next thread, push the previous one first.
707
5
          if (had_nt_regs) {
708
2
            m_thread_data.push_back(thread_data);
709
2
            thread_data = ThreadData();
710
2
            had_nt_regs = false;
711
2
          }
712
713
5
          thread_data.gpregset = note.data;
714
5
          thread_data.tid = tid;
715
5
          if (thread_data.gpregset.GetByteSize() == 0)
716
0
            return llvm::make_error<llvm::StringError>(
717
0
                "Could not find general purpose registers note in core file.",
718
0
                llvm::inconvertibleErrorCode());
719
5
          had_nt_regs = true;
720
5
        } else if (note.info.n_type == NETBSD::AARCH64::NT_FPREGS) {
721
5
          if (!had_nt_regs || tid != thread_data.tid)
722
0
            return llvm::make_error<llvm::StringError>(
723
0
                "Error parsing NetBSD core(5) notes: Unexpected order "
724
0
                "of NOTEs PT_GETFPREG before PT_GETREG",
725
0
                llvm::inconvertibleErrorCode());
726
5
          thread_data.notes.push_back(note);
727
5
        }
728
10
      } break;
729
12
      case llvm::Triple::x86: {
730
        // Assume order PT_GETREGS, PT_GETFPREGS
731
12
        if (note.info.n_type == NETBSD::I386::NT_REGS) {
732
          // If this is the next thread, push the previous one first.
733
6
          if (had_nt_regs) {
734
3
            m_thread_data.push_back(thread_data);
735
3
            thread_data = ThreadData();
736
3
            had_nt_regs = false;
737
3
          }
738
739
6
          thread_data.gpregset = note.data;
740
6
          thread_data.tid = tid;
741
6
          if (thread_data.gpregset.GetByteSize() == 0)
742
0
            return llvm::make_error<llvm::StringError>(
743
0
                "Could not find general purpose registers note in core file.",
744
0
                llvm::inconvertibleErrorCode());
745
6
          had_nt_regs = true;
746
6
        } else if (note.info.n_type == NETBSD::I386::NT_FPREGS) {
747
6
          if (!had_nt_regs || tid != thread_data.tid)
748
0
            return llvm::make_error<llvm::StringError>(
749
0
                "Error parsing NetBSD core(5) notes: Unexpected order "
750
0
                "of NOTEs PT_GETFPREG before PT_GETREG",
751
0
                llvm::inconvertibleErrorCode());
752
6
          thread_data.notes.push_back(note);
753
6
        }
754
12
      } break;
755
24
      case llvm::Triple::x86_64: {
756
        // Assume order PT_GETREGS, PT_GETFPREGS
757
24
        if (note.info.n_type == NETBSD::AMD64::NT_REGS) {
758
          // If this is the next thread, push the previous one first.
759
12
          if (had_nt_regs) {
760
5
            m_thread_data.push_back(thread_data);
761
5
            thread_data = ThreadData();
762
5
            had_nt_regs = false;
763
5
          }
764
765
12
          thread_data.gpregset = note.data;
766
12
          thread_data.tid = tid;
767
12
          if (thread_data.gpregset.GetByteSize() == 0)
768
0
            return llvm::make_error<llvm::StringError>(
769
0
                "Could not find general purpose registers note in core file.",
770
0
                llvm::inconvertibleErrorCode());
771
12
          had_nt_regs = true;
772
12
        } else if (note.info.n_type == NETBSD::AMD64::NT_FPREGS) {
773
12
          if (!had_nt_regs || tid != thread_data.tid)
774
0
            return llvm::make_error<llvm::StringError>(
775
0
                "Error parsing NetBSD core(5) notes: Unexpected order "
776
0
                "of NOTEs PT_GETFPREG before PT_GETREG",
777
0
                llvm::inconvertibleErrorCode());
778
12
          thread_data.notes.push_back(note);
779
12
        }
780
24
      } break;
781
24
      default:
782
0
        break;
783
46
      }
784
46
    }
785
72
  }
786
787
  // Push the last thread.
788
13
  if (had_nt_regs)
789
13
    m_thread_data.push_back(thread_data);
790
791
13
  if (m_thread_data.empty())
792
0
    return llvm::make_error<llvm::StringError>(
793
0
        "Error parsing NetBSD core(5) notes: No threads information "
794
0
        "specified in notes",
795
0
        llvm::inconvertibleErrorCode());
796
797
13
  if (m_thread_data.size() != nlwps)
798
0
    return llvm::make_error<llvm::StringError>(
799
0
        "Error parsing NetBSD core(5) notes: Mismatch between the number "
800
0
        "of LWPs in netbsd_elfcore_procinfo and the number of LWPs specified "
801
0
        "by MD notes",
802
0
        llvm::inconvertibleErrorCode());
803
804
  // Signal targeted at the whole process.
805
13
  if (siglwp == 0) {
806
2
    for (auto &data : m_thread_data)
807
4
      data.signo = signo;
808
2
  }
809
  // Signal destined for a particular LWP.
810
11
  else {
811
11
    bool passed = false;
812
813
11
    for (auto &data : m_thread_data) {
814
11
      if (data.tid == siglwp) {
815
11
        data.signo = signo;
816
11
        passed = true;
817
11
        break;
818
11
      }
819
11
    }
820
821
11
    if (!passed)
822
0
      return llvm::make_error<llvm::StringError>(
823
0
          "Error parsing NetBSD core(5) notes: Signal passed to unknown LWP",
824
0
          llvm::inconvertibleErrorCode());
825
11
  }
826
827
13
  return llvm::Error::success();
828
13
}
829
830
0
llvm::Error ProcessElfCore::parseOpenBSDNotes(llvm::ArrayRef<CoreNote> notes) {
831
0
  ThreadData thread_data = {};
832
0
  for (const auto &note : notes) {
833
    // OpenBSD per-thread information is stored in notes named "OpenBSD@nnn" so
834
    // match on the initial part of the string.
835
0
    if (!llvm::StringRef(note.info.n_name).startswith("OpenBSD"))
836
0
      continue;
837
838
0
    switch (note.info.n_type) {
839
0
    case OPENBSD::NT_PROCINFO:
840
0
      ParseOpenBSDProcInfo(thread_data, note.data);
841
0
      break;
842
0
    case OPENBSD::NT_AUXV:
843
0
      m_auxv = note.data;
844
0
      break;
845
0
    case OPENBSD::NT_REGS:
846
0
      thread_data.gpregset = note.data;
847
0
      break;
848
0
    default:
849
0
      thread_data.notes.push_back(note);
850
0
      break;
851
0
    }
852
0
  }
853
0
  if (thread_data.gpregset.GetByteSize() == 0) {
854
0
    return llvm::make_error<llvm::StringError>(
855
0
        "Could not find general purpose registers note in core file.",
856
0
        llvm::inconvertibleErrorCode());
857
0
  }
858
0
  m_thread_data.push_back(thread_data);
859
0
  return llvm::Error::success();
860
0
}
861
862
/// A description of a linux process usually contains the following NOTE
863
/// entries:
864
/// - NT_PRPSINFO - General process information like pid, uid, name, ...
865
/// - NT_SIGINFO - Information about the signal that terminated the process
866
/// - NT_AUXV - Process auxiliary vector
867
/// - NT_FILE - Files mapped into memory
868
/// 
869
/// Additionally, for each thread in the process the core file will contain at
870
/// least the NT_PRSTATUS note, containing the thread id and general purpose
871
/// registers. It may include additional notes for other register sets (floating
872
/// point and vector registers, ...). The tricky part here is that some of these
873
/// notes have "CORE" in their owner fields, while other set it to "LINUX".
874
44
llvm::Error ProcessElfCore::parseLinuxNotes(llvm::ArrayRef<CoreNote> notes) {
875
44
  const ArchSpec &arch = GetArchitecture();
876
44
  bool have_prstatus = false;
877
44
  bool have_prpsinfo = false;
878
44
  ThreadData thread_data;
879
497
  for (const auto &note : notes) {
880
497
    if (note.info.n_name != "CORE" && 
note.info.n_name != "LINUX"207
)
881
0
      continue;
882
883
497
    if ((note.info.n_type == ELF::NT_PRSTATUS && 
have_prstatus60
) ||
884
497
        
(481
note.info.n_type == ELF::NT_PRPSINFO481
&&
have_prpsinfo43
)) {
885
16
      assert(thread_data.gpregset.GetByteSize() > 0);
886
      // Add the new thread to thread list
887
16
      m_thread_data.push_back(thread_data);
888
16
      thread_data = ThreadData();
889
16
      have_prstatus = false;
890
16
      have_prpsinfo = false;
891
16
    }
892
893
497
    switch (note.info.n_type) {
894
60
    case ELF::NT_PRSTATUS: {
895
60
      have_prstatus = true;
896
60
      ELFLinuxPrStatus prstatus;
897
60
      Status status = prstatus.Parse(note.data, arch);
898
60
      if (status.Fail())
899
0
        return status.ToError();
900
60
      thread_data.prstatus_sig = prstatus.pr_cursig;
901
60
      thread_data.tid = prstatus.pr_pid;
902
60
      uint32_t header_size = ELFLinuxPrStatus::GetSize(arch);
903
60
      size_t len = note.data.GetByteSize() - header_size;
904
60
      thread_data.gpregset = DataExtractor(note.data, header_size, len);
905
60
      break;
906
60
    }
907
43
    case ELF::NT_PRPSINFO: {
908
43
      have_prpsinfo = true;
909
43
      ELFLinuxPrPsInfo prpsinfo;
910
43
      Status status = prpsinfo.Parse(note.data, arch);
911
43
      if (status.Fail())
912
0
        return status.ToError();
913
43
      thread_data.name.assign (prpsinfo.pr_fname, strnlen (prpsinfo.pr_fname, sizeof (prpsinfo.pr_fname)));
914
43
      SetID(prpsinfo.pr_pid);
915
43
      break;
916
43
    }
917
47
    case ELF::NT_SIGINFO: {
918
47
      ELFLinuxSigInfo siginfo;
919
47
      Status status = siginfo.Parse(note.data, arch);
920
47
      if (status.Fail())
921
0
        return status.ToError();
922
47
      thread_data.signo = siginfo.si_signo;
923
47
      thread_data.code = siginfo.si_code;
924
47
      break;
925
47
    }
926
41
    case ELF::NT_FILE: {
927
41
      m_nt_file_entries.clear();
928
41
      lldb::offset_t offset = 0;
929
41
      const uint64_t count = note.data.GetAddress(&offset);
930
41
      note.data.GetAddress(&offset); // Skip page size
931
541
      for (uint64_t i = 0; i < count; 
++i500
) {
932
500
        NT_FILE_Entry entry;
933
500
        entry.start = note.data.GetAddress(&offset);
934
500
        entry.end = note.data.GetAddress(&offset);
935
500
        entry.file_ofs = note.data.GetAddress(&offset);
936
500
        m_nt_file_entries.push_back(entry);
937
500
      }
938
541
      for (uint64_t i = 0; i < count; 
++i500
) {
939
500
        const char *path = note.data.GetCStr(&offset);
940
500
        if (path && path[0])
941
500
          m_nt_file_entries[i].path.assign(path);
942
500
      }
943
41
      break;
944
47
    }
945
43
    case ELF::NT_AUXV:
946
43
      m_auxv = note.data;
947
43
      break;
948
263
    default:
949
263
      thread_data.notes.push_back(note);
950
263
      break;
951
497
    }
952
497
  }
953
  // Add last entry in the note section
954
44
  if (have_prstatus)
955
44
    m_thread_data.push_back(thread_data);
956
44
  return llvm::Error::success();
957
44
}
958
959
/// Parse Thread context from PT_NOTE segment and store it in the thread list
960
/// A note segment consists of one or more NOTE entries, but their types and
961
/// meaning differ depending on the OS.
962
llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
963
    const elf::ELFProgramHeader &segment_header,
964
66
    const DataExtractor &segment_data) {
965
66
  assert(segment_header.p_type == llvm::ELF::PT_NOTE);
966
967
66
  auto notes_or_error = parseSegment(segment_data);
968
66
  if(!notes_or_error)
969
0
    return notes_or_error.takeError();
970
66
  switch (GetArchitecture().GetTriple().getOS()) {
971
9
  case llvm::Triple::FreeBSD:
972
9
    return parseFreeBSDNotes(*notes_or_error);
973
44
  case llvm::Triple::Linux:
974
44
    return parseLinuxNotes(*notes_or_error);
975
13
  case llvm::Triple::NetBSD:
976
13
    return parseNetBSDNotes(*notes_or_error);
977
0
  case llvm::Triple::OpenBSD:
978
0
    return parseOpenBSDNotes(*notes_or_error);
979
0
  default:
980
0
    return llvm::make_error<llvm::StringError>(
981
0
        "Don't know how to parse core file. Unsupported OS.",
982
0
        llvm::inconvertibleErrorCode());
983
66
  }
984
66
}
985
986
66
uint32_t ProcessElfCore::GetNumThreadContexts() {
987
66
  if (!m_thread_data_valid)
988
0
    DoLoadCore();
989
66
  return m_thread_data.size();
990
66
}
991
992
418
ArchSpec ProcessElfCore::GetArchitecture() {
993
418
  ArchSpec arch = m_core_module_sp->GetObjectFile()->GetArchitecture();
994
995
418
  ArchSpec target_arch = GetTarget().GetArchitecture();
996
418
  arch.MergeFrom(target_arch);
997
998
  // On MIPS there is no way to differentiate betwenn 32bit and 64bit core
999
  // files and this information can't be merged in from the target arch so we
1000
  // fail back to unconditionally returning the target arch in this config.
1001
418
  if (target_arch.IsMIPS()) {
1002
0
    return target_arch;
1003
0
  }
1004
1005
418
  return arch;
1006
418
}
1007
1008
84
DataExtractor ProcessElfCore::GetAuxvData() {
1009
84
  const uint8_t *start = m_auxv.GetDataStart();
1010
84
  size_t len = m_auxv.GetByteSize();
1011
84
  lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(start, len));
1012
84
  return DataExtractor(buffer, GetByteOrder(), GetAddressByteSize());
1013
84
}
1014
1015
66
bool ProcessElfCore::GetProcessInfo(ProcessInstanceInfo &info) {
1016
66
  info.Clear();
1017
66
  info.SetProcessID(GetID());
1018
66
  info.SetArchitecture(GetArchitecture());
1019
66
  lldb::ModuleSP module_sp = GetTarget().GetExecutableModule();
1020
66
  if (module_sp) {
1021
18
    const bool add_exe_file_as_first_arg = false;
1022
18
    info.SetExecutableFile(GetTarget().GetExecutableModule()->GetFileSpec(),
1023
18
                           add_exe_file_as_first_arg);
1024
18
  }
1025
66
  return true;
1026
66
}