6
6
//
7
7
// ===----------------------------------------------------------------------===//
8
8
9
+ #include < cstddef>
9
10
#include < cstdlib>
10
11
11
12
#include < memory>
12
13
#include < mutex>
14
+ #include < tuple>
13
15
16
+ #include " Plugins/ObjectFile/ELF/ELFHeader.h"
14
17
#include " lldb/Core/Module.h"
15
18
#include " lldb/Core/ModuleSpec.h"
16
19
#include " lldb/Core/PluginManager.h"
33
36
#include " Plugins/Process/elf-core/RegisterUtilities.h"
34
37
#include " ProcessElfCore.h"
35
38
#include " ThreadElfCore.h"
39
+ #include " lldb/lldb-types.h"
36
40
37
41
using namespace lldb_private ;
38
42
namespace ELF = llvm::ELF;
@@ -250,6 +254,9 @@ Status ProcessElfCore::DoLoadCore() {
250
254
}
251
255
}
252
256
257
+ // Try to find gnu build id before we load the executable.
258
+ UpdateBuildIdForNTFileEntries ();
259
+
253
260
// Core files are useless without the main executable. See if we can locate
254
261
// the main executable using data we found in the core file notes.
255
262
lldb::ModuleSP exe_module_sp = GetTarget ().GetExecutableModule ();
@@ -258,6 +265,7 @@ Status ProcessElfCore::DoLoadCore() {
258
265
if (!m_nt_file_entries.empty ()) {
259
266
ModuleSpec exe_module_spec;
260
267
exe_module_spec.GetArchitecture () = arch;
268
+ exe_module_spec.GetUUID () = m_nt_file_entries[0 ].uuid ;
261
269
exe_module_spec.GetFileSpec ().SetFile (m_nt_file_entries[0 ].path ,
262
270
FileSpec::Style::native);
263
271
if (exe_module_spec.GetFileSpec ()) {
@@ -271,6 +279,17 @@ Status ProcessElfCore::DoLoadCore() {
271
279
return error;
272
280
}
273
281
282
+ void ProcessElfCore::UpdateBuildIdForNTFileEntries () {
283
+ if (!m_nt_file_entries.empty ()) {
284
+ for (NT_FILE_Entry &entry : m_nt_file_entries) {
285
+ std::optional<UUID> uuid =
286
+ FindNoteInCoreMemory (entry.start , llvm::ELF::NT_GNU_BUILD_ID);
287
+ if (uuid)
288
+ entry.uuid = uuid.value ();
289
+ }
290
+ }
291
+ }
292
+
274
293
lldb_private::DynamicLoader *ProcessElfCore::GetDynamicLoader () {
275
294
if (m_dyld_up.get () == nullptr )
276
295
m_dyld_up.reset (DynamicLoader::FindPlugin (
@@ -570,11 +589,13 @@ static void ParseOpenBSDProcInfo(ThreadData &thread_data,
570
589
}
571
590
572
591
llvm::Expected<std::vector<CoreNote>>
573
- ProcessElfCore::parseSegment (const DataExtractor &segment) {
592
+ ProcessElfCore::parseSegment (const DataExtractor &segment,
593
+ unsigned long segment_size) {
574
594
lldb::offset_t offset = 0 ;
575
595
std::vector<CoreNote> result;
576
-
577
- while (offset < segment.GetByteSize ()) {
596
+ unsigned long note_size =
597
+ segment_size == 0 ? segment.GetByteSize () : segment_size;
598
+ while (offset < note_size) {
578
599
ELFNote note = ELFNote ();
579
600
if (!note.Parse (segment, &offset))
580
601
return llvm::make_error<llvm::StringError>(
@@ -983,6 +1004,66 @@ llvm::Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
983
1004
}
984
1005
}
985
1006
1007
+ bool ProcessElfCore::IsElf (lldb::addr_t address) {
1008
+ uint8_t buf[4 ];
1009
+ Status error;
1010
+ size_t byte_read = ReadMemory (address, buf, 4 , error);
1011
+ if (byte_read != 4 )
1012
+ return false ;
1013
+ return elf::ELFHeader::MagicBytesMatch (buf);
1014
+ }
1015
+
1016
+ std::optional<UUID> ProcessElfCore::FindNoteInCoreMemory (lldb::addr_t address,
1017
+ uint32_t type) {
1018
+ if (!IsElf (address))
1019
+ return std::nullopt;
1020
+ const uint32_t addr_size = GetAddressByteSize ();
1021
+ const size_t elf_header_size = addr_size == 4 ? sizeof (llvm::ELF::Elf32_Ehdr)
1022
+ : sizeof (llvm::ELF::Elf64_Ehdr);
1023
+
1024
+ unsigned char buf[4096 ];
1025
+ Status error;
1026
+ size_t byte_read = ReadMemory (address, buf, elf_header_size, error);
1027
+ if (byte_read != elf_header_size)
1028
+ return std::nullopt;
1029
+ DataExtractor data (buf, 4096 , GetByteOrder (), addr_size);
1030
+ lldb::offset_t offset = 0 ;
1031
+
1032
+ elf::ELFHeader elf_header;
1033
+ elf_header.Parse (data, &offset);
1034
+
1035
+ const lldb::addr_t ph_addr = address + elf_header.e_phoff ;
1036
+
1037
+ for (unsigned int i = 0 ; i < elf_header.e_phnum ; ++i) {
1038
+ byte_read = ReadMemory (ph_addr + i * elf_header.e_phentsize , buf,
1039
+ elf_header.e_phentsize , error);
1040
+ if (byte_read != elf_header.e_phentsize )
1041
+ break ;
1042
+ offset = 0 ;
1043
+ elf::ELFProgramHeader program_header;
1044
+ program_header.Parse (data, &offset);
1045
+ if (program_header.p_type != llvm::ELF::PT_NOTE)
1046
+ continue ;
1047
+
1048
+ byte_read =
1049
+ ReadMemory (program_header.p_vaddr , buf, program_header.p_memsz , error);
1050
+ if (byte_read != program_header.p_memsz )
1051
+ continue ;
1052
+
1053
+ auto notes_or_error = parseSegment (data, program_header.p_memsz );
1054
+ if (!notes_or_error)
1055
+ return std::nullopt;
1056
+ for (const CoreNote ¬e : *notes_or_error) {
1057
+ if (note.info .n_namesz == 4 && note.info .n_type == type) {
1058
+ if (" GNU" == note.info .n_name )
1059
+ return UUID (llvm::ArrayRef<uint8_t >(
1060
+ note.data .GetDataStart (), note.info .n_descsz /* byte size*/ ));
1061
+ }
1062
+ }
1063
+ }
1064
+ return std::nullopt;
1065
+ }
1066
+
986
1067
uint32_t ProcessElfCore::GetNumThreadContexts () {
987
1068
if (!m_thread_data_valid)
988
1069
DoLoadCore ();
0 commit comments