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