diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp | 116 |
1 files changed, 68 insertions, 48 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index 122298d87bf8..9131367bf223 100644 --- a/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/contrib/llvm-project/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -10,6 +10,7 @@ #include <algorithm> #include <cassert> +#include <optional> #include <unordered_map> #include "lldb/Core/FileSpecList.h" @@ -121,6 +122,8 @@ public: static unsigned RelocAddend64(const ELFRelocation &rel); + bool IsRela() { return (reloc.is<ELFRela *>()); } + private: typedef llvm::PointerUnion<ELFRel *, ELFRela *> RelocUnion; @@ -318,6 +321,18 @@ static uint32_t ppc64VariantFromElfFlags(const elf::ELFHeader &header) { return ArchSpec::eCore_ppc64_generic; } +static uint32_t loongarchVariantFromElfFlags(const elf::ELFHeader &header) { + uint32_t fileclass = header.e_ident[EI_CLASS]; + switch (fileclass) { + case llvm::ELF::ELFCLASS32: + return ArchSpec::eLoongArchSubType_loongarch32; + case llvm::ELF::ELFCLASS64: + return ArchSpec::eLoongArchSubType_loongarch64; + default: + return ArchSpec::eLoongArchSubType_unknown; + } +} + static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { if (header.e_machine == llvm::ELF::EM_MIPS) return mipsVariantFromElfFlags(header); @@ -325,6 +340,8 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { return ppc64VariantFromElfFlags(header); else if (header.e_machine == llvm::ELF::EM_RISCV) return riscvVariantFromElfFlags(header); + else if (header.e_machine == llvm::ELF::EM_LOONGARCH) + return loongarchVariantFromElfFlags(header); return LLDB_INVALID_CPUTYPE; } @@ -430,8 +447,8 @@ bool ObjectFileELF::MagicBytesMatch(DataBufferSP &data_sp, } static uint32_t calc_crc32(uint32_t init, const DataExtractor &data) { - return llvm::crc32( - init, llvm::makeArrayRef(data.GetDataStart(), data.GetByteSize())); + return llvm::crc32(init, + llvm::ArrayRef(data.GetDataStart(), data.GetByteSize())); } uint32_t ObjectFileELF::CalculateELFNotesSegmentsCRC32( @@ -627,13 +644,13 @@ size_t ObjectFileELF::GetModuleSpecifications( if (gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. u32le data(gnu_debuglink_crc); - uuid = UUID::fromData(&data, sizeof(data)); + uuid = UUID(&data, sizeof(data)); } else if (core_notes_crc) { // Use 8 bytes - first 4 bytes for *magic* prefix, mainly to make // it look different form .gnu_debuglink crc followed by 4 bytes // of note segments crc. u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)}; - uuid = UUID::fromData(data, sizeof(data)); + uuid = UUID(data, sizeof(data)); } } @@ -788,7 +805,7 @@ UUID ObjectFileELF::GetUUID() { // look different form .gnu_debuglink crc - followed by 4 bytes of note // segments crc. u32le data[] = {u32le(g_core_uuid_magic), u32le(core_notes_crc)}; - m_uuid = UUID::fromData(data, sizeof(data)); + m_uuid = UUID(data, sizeof(data)); } } else { if (!m_gnu_debuglink_crc) @@ -796,7 +813,7 @@ UUID ObjectFileELF::GetUUID() { if (m_gnu_debuglink_crc) { // Use 4 bytes of crc from the .gnu_debuglink section. u32le data(m_gnu_debuglink_crc); - m_uuid = UUID::fromData(&data, sizeof(data)); + m_uuid = UUID(&data, sizeof(data)); } } } @@ -804,9 +821,9 @@ UUID ObjectFileELF::GetUUID() { return m_uuid; } -llvm::Optional<FileSpec> ObjectFileELF::GetDebugLink() { +std::optional<FileSpec> ObjectFileELF::GetDebugLink() { if (m_gnu_debuglink_file.empty()) - return llvm::None; + return std::nullopt; return FileSpec(m_gnu_debuglink_file); } @@ -1134,7 +1151,7 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data, if (note.n_descsz >= 4) { if (const uint8_t *buf = data.PeekData(offset, note.n_descsz)) { // Save the build id as the UUID for the module. - uuid = UUID::fromData(buf, note.n_descsz); + uuid = UUID(buf, note.n_descsz); } else { error.SetErrorString("failed to read GNU_BUILD_ID note payload"); return error; @@ -1750,22 +1767,22 @@ public: return llvm::formatv("{0}[{1}]", SegmentName, SegmentCount).str(); } - llvm::Optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) { + std::optional<VMRange> GetAddressInfo(const ELFProgramHeader &H) { if (H.p_memsz == 0) { LLDB_LOG(Log, "Ignoring zero-sized {0} segment. Corrupt object file?", SegmentName); - return llvm::None; + return std::nullopt; } if (Segments.overlaps(H.p_vaddr, H.p_vaddr + H.p_memsz)) { LLDB_LOG(Log, "Ignoring overlapping {0} segment. Corrupt object file?", SegmentName); - return llvm::None; + return std::nullopt; } return VMRange(H.p_vaddr, H.p_memsz); } - llvm::Optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) { + std::optional<SectionAddressInfo> GetAddressInfo(const ELFSectionHeader &H) { VMRange Range = GetVMRange(H); SectionSP Segment; auto It = Segments.find(Range.GetRangeBase()); @@ -1785,7 +1802,7 @@ public: if (Range.GetByteSize() > 0 && Sections.overlaps(Range.GetRangeBase(), Range.GetRangeEnd())) { LLDB_LOG(Log, "Ignoring overlapping section. Corrupt object file?"); - return llvm::None; + return std::nullopt; } if (Segment) Range.Slide(-Segment->GetFileAddress()); @@ -1935,7 +1952,7 @@ std::shared_ptr<ObjectFileELF> ObjectFileELF::GetGnuDebugDataObjectFile() { auto err = lldb_private::lzma::uncompress(data.GetData(), uncompressedData); if (err) { GetModule()->ReportWarning( - "An error occurred while decompression the section %s: %s", + "An error occurred while decompression the section {0}: {1}", section->GetName().AsCString(), llvm::toString(std::move(err)).c_str()); return nullptr; } @@ -2223,23 +2240,6 @@ unsigned ObjectFileELF::ParseSymbols(Symtab *symtab, user_id_t start_id, // symbols. See above for more details. uint64_t symbol_value = symbol.st_value + symbol_value_offset; - if (symbol_section_sp == nullptr && shndx == SHN_ABS && - symbol.st_size != 0) { - // We don't have a section for a symbol with non-zero size. Create a new - // section for it so the address range covered by the symbol is also - // covered by the module (represented through the section list). It is - // needed so module lookup for the addresses covered by this symbol will - // be successfull. This case happens for absolute symbols. - ConstString fake_section_name(std::string(".absolute.") + symbol_name); - symbol_section_sp = - std::make_shared<Section>(module_sp, this, SHN_ABS, fake_section_name, - eSectionTypeAbsoluteAddress, symbol_value, - symbol.st_size, 0, 0, 0, SHF_ALLOC); - - module_section_list->AddSection(symbol_section_sp); - section_list->AddSection(symbol_section_sp); - } - if (symbol_section_sp && CalculateType() != ObjectFile::Type::eTypeObjectFile) symbol_value -= symbol_section_sp->GetFileAddress(); @@ -2614,25 +2614,46 @@ unsigned ObjectFileELF::ApplyRelocations( } for (unsigned i = 0; i < num_relocations; ++i) { - if (!rel.Parse(rel_data, &offset)) + if (!rel.Parse(rel_data, &offset)) { + GetModule()->ReportError(".rel{0}[{1:d}] failed to parse relocation", + rel_section->GetName().AsCString(), i); break; - + } Symbol *symbol = nullptr; if (hdr->Is32Bit()) { switch (reloc_type(rel)) { case R_386_32: + symbol = symtab->FindSymbolByID(reloc_symbol(rel)); + if (symbol) { + addr_t f_offset = + rel_section->GetFileOffset() + ELFRelocation::RelocOffset32(rel); + DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer(); + // ObjectFileELF creates a WritableDataBuffer in CreateInstance. + WritableDataBuffer *data_buffer = + llvm::cast<WritableDataBuffer>(data_buffer_sp.get()); + uint32_t *dst = reinterpret_cast<uint32_t *>( + data_buffer->GetBytes() + f_offset); + + addr_t value = symbol->GetAddressRef().GetFileAddress(); + if (rel.IsRela()) { + value += ELFRelocation::RelocAddend32(rel); + } else { + value += *dst; + } + *dst = value; + } else { + GetModule()->ReportError(".rel{0}[{1}] unknown symbol id: {2:d}", + rel_section->GetName().AsCString(), i, + reloc_symbol(rel)); + } + break; case R_386_PC32: default: - // FIXME: This asserts with this input: - // - // foo.cpp - // int main(int argc, char **argv) { return 0; } - // - // clang++.exe --target=i686-unknown-linux-gnu -g -c foo.cpp -o foo.o - // - // and running this on the foo.o module. - assert(false && "unexpected relocation type"); + GetModule()->ReportError("unsupported 32-bit relocation:" + " .rel{0}[{1}], type {2}", + rel_section->GetName().AsCString(), i, + reloc_type(rel)); } } else { switch (reloc_type(rel)) { @@ -3375,7 +3396,7 @@ size_t ObjectFileELF::ReadSectionData(Section *section, GetByteOrder() == eByteOrderLittle, GetAddressByteSize() == 8); if (!Decompressor) { GetModule()->ReportWarning( - "Unable to initialize decompressor for section '%s': %s", + "Unable to initialize decompressor for section '{0}': {1}", section->GetName().GetCString(), llvm::toString(Decompressor.takeError()).c_str()); section_data.Clear(); @@ -3386,10 +3407,9 @@ size_t ObjectFileELF::ReadSectionData(Section *section, std::make_shared<DataBufferHeap>(Decompressor->getDecompressedSize(), 0); if (auto error = Decompressor->decompress( {buffer_sp->GetBytes(), size_t(buffer_sp->GetByteSize())})) { - GetModule()->ReportWarning( - "Decompression of section '%s' failed: %s", - section->GetName().GetCString(), - llvm::toString(std::move(error)).c_str()); + GetModule()->ReportWarning("Decompression of section '{0}' failed: {1}", + section->GetName().GetCString(), + llvm::toString(std::move(error)).c_str()); section_data.Clear(); return 0; } |