Debugging ELF relocatable files using LLDB

It looks like LLDB doesn't like ELF relocatable files for debugging
and asserts with the following message when tried

     <path to>/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp:2228:
unsigned int ObjectFileELF::RelocateSection(.....): Assertion `false
&& "unexpected relocation type"' failed.

Are we not supposed to debug ELF relocatable files on LLDB or am I
missing something?

If we cannot debug the relocatable files, is it _simply_ because those
files lack program headers (program memory map) and relocations are
yet to be processed (for debug info) or there are other reasons?

For our target, the assembler output itself is a self contained ELF
and hence will not have external references (both code and data). I am
wondering if I can debug these ELF files on LLDB with minimal changes
which does not require a full (or proper) linking step and would
appreciate any pointers on that.

Thanks,
Ramana

Looks like you just need to add support for the 32 bit relocations:

if (hdr->Is32Bit()) {
switch (reloc_type(rel)) {
case R_386_32:
case R_386_PC32:
default:
assert(false && “unexpected relocation type”);
}
} else {
switch (reloc_type(rel)) {
case R_X86_64_64: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
addr_t value = symbol->GetAddressRef().GetFileAddress();
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
uint64_t *dst = reinterpret_cast<uint64_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset64(rel));
*dst = value + ELFRelocation::RelocAddend64(rel);
}
break;
}
case R_X86_64_32:
case R_X86_64_32S: {
symbol = symtab->FindSymbolByID(reloc_symbol(rel));
if (symbol) {
addr_t value = symbol->GetAddressRef().GetFileAddress();
value += ELFRelocation::RelocAddend32(rel);
assert(
(reloc_type(rel) == R_X86_64_32 && (value <= UINT32_MAX)) ||
(reloc_type(rel) == R_X86_64_32S &&
((int64_t)value <= INT32_MAX && (int64_t)value >= INT32_MIN)));
uint32_t truncated_addr = (value & 0xFFFFFFFF);
DataBufferSP &data_buffer_sp = debug_data.GetSharedDataBuffer();
uint32_t *dst = reinterpret_cast<uint32_t *>(
data_buffer_sp->GetBytes() + rel_section->GetFileOffset() +
ELFRelocation::RelocOffset32(rel));
*dst = truncated_addr;
}
break;
}
case R_X86_64_PC32:
default:
assert(false && “unexpected relocation type”);
}
}

I am guessing you will do something similar to the x86-64 stuff.

I tried to mimic the x86_64 relocations handling for our target but
getting segmentation fault while trying to write to the 'dst'
location.

In fact, the x86_64 also segfaults while trying to write to 'dst'
location. I just tried to debug the following simple program for
x86_64.

main.c:
    int main () {
       return 0;
    }

$ clang main.c -o main_64b.o --target=x86_64 -c -g
$ lldb main_64b.o
(lldb) target create "main_64b.o"
Current executable set to 'main_64b.o' (x86_64).
(lldb) source list
Segmentation fault (core dumped)

Am I doing something wrong or support for debugging the x86_64 ELF
relocatable files using LLDB is broken?

BTW, I am using LLVM v3.6 and LLDB v3.6.

Regards,
Ramana

I uploaded a CL for review what fixes the crash you are experimenting at https://reviews.llvm.org/D30251 (we are mapping the files into memory as read only and then trying to write into it) but I think nobody tests LLDB with relocable object files so you might run into a lot of bugs in the way. Also I suggest to switch to a newer version of LLDB (preferably ToT) as 3.6 is fairly old and known to have a lot of bugs on Linux and on ARM.

Tamas