Index: test/tools/llvm-objcopy/ELF/relocations-no-symtab.test =================================================================== --- /dev/null +++ test/tools/llvm-objcopy/ELF/relocations-no-symtab.test @@ -0,0 +1,55 @@ +## Check that we can copy an object that has a relocation +## without symbol associated even when there is no symbol table. + +# RUN: yaml2obj --docnum=1 %s > %t1 +# RUN: llvm-objcopy %t1 %t2 +# RUN: llvm-readobj --relocations %t2 | FileCheck %s + +# CHECK: Relocations [ +# CHECK-NEXT: Section {{.*}} .rel.text { +# CHECK-NEXT: 0x1000 R_X86_64_RELATIVE - 0x0 +# CHECK-NEXT: } +# CHECK-NEXT:] + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .rel.text + Type: SHT_REL + Info: .text + Relocations: + - Offset: 0x1000 + Type: R_X86_64_RELATIVE + +## Check that we report an error when relocation refers to a symbol, +## but we have no symbol table. + +# RUN: yaml2obj --docnum=2 %s > %t3 +# RUN: not llvm-objcopy %t3 %t4 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: '.rel.text': relocation references a symbol (1), but there is no symbol table + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + - Name: .rel.text + Type: SHT_REL + Info: .text + Relocations: + - Offset: 0x1000 + Symbol: 1 + Type: R_X86_64_NONE Index: tools/llvm-objcopy/ELF/Object.cpp =================================================================== --- tools/llvm-objcopy/ELF/Object.cpp +++ tools/llvm-objcopy/ELF/Object.cpp @@ -815,7 +815,8 @@ } for (const Relocation &R : Relocations) { - if (!R.RelocSymbol->DefinedIn || !ToRemove(R.RelocSymbol->DefinedIn)) + if (!R.RelocSymbol || !R.RelocSymbol->DefinedIn || + !ToRemove(R.RelocSymbol->DefinedIn)) continue; return createStringError(llvm::errc::invalid_argument, "section '%s' cannot be removed: (%s+0x%" PRIx64 @@ -868,7 +869,8 @@ for (const auto &Reloc : Relocations) { Buf->r_offset = Reloc.Offset; setAddend(*Buf, Reloc.Addend); - Buf->setSymbolAndType(Reloc.RelocSymbol->Index, Reloc.Type, false); + Buf->setSymbolAndType(Reloc.RelocSymbol ? Reloc.RelocSymbol->Index : 0, + Reloc.Type, false); ++Buf; } } @@ -893,7 +895,7 @@ Error RelocationSection::removeSymbols( function_ref ToRemove) { for (const Relocation &Reloc : Relocations) - if (ToRemove(*Reloc.RelocSymbol)) + if (Reloc.RelocSymbol && ToRemove(*Reloc.RelocSymbol)) return createStringError( llvm::errc::invalid_argument, "not stripping symbol '%s' because it is named in a relocation", @@ -1418,7 +1420,14 @@ ToAdd.Offset = Rel.r_offset; getAddend(ToAdd.Addend, Rel); ToAdd.Type = Rel.getType(false); - ToAdd.RelocSymbol = SymbolTable->getSymbolByIndex(Rel.getSymbol(false)); + + if (uint32_t Sym = Rel.getSymbol(false)) { + if (!SymbolTable) + error("'" + Relocs->Name + "': relocation references a symbol (" + + Twine(Sym) + "), but there is no symbol table"); + ToAdd.RelocSymbol = SymbolTable->getSymbolByIndex(Sym); + } + Relocs->addRelocation(ToAdd); } }