Skip to content

Commit 489a735

Browse files
committed
[ELF] Fix a null pointer dereference when --emit-relocs and --strip-debug are used together
Fixes https://bugs.llvm.org//show_bug.cgi?id=44878 When --strip-debug is specified, .debug* are removed from inputSections while .rel[a].debug* (incorrectly) remain. LinkerScript::addOrphanSections() requires the output section of a relocated InputSectionBase to be created first. .debug* are not in inputSections -> output sections .debug* are not created -> getOutputSectionName(.rel[a].debug*) dereferences a null pointer. Fix the null pointer dereference by deleting .rel[a].debug* from inputSections as well. Reviewed By: grimar, nickdesaulniers Differential Revision: https://reviews.llvm.org/D74510 (cherry picked from commit 6c73246)
1 parent d32170d commit 489a735

File tree

4 files changed

+36
-4
lines changed

4 files changed

+36
-4
lines changed

lld/ELF/Driver.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,8 +1906,17 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
19061906

19071907
// We do not want to emit debug sections if --strip-all
19081908
// or -strip-debug are given.
1909-
return config->strip != StripPolicy::None &&
1910-
(s->name.startswith(".debug") || s->name.startswith(".zdebug"));
1909+
if (config->strip == StripPolicy::None)
1910+
return false;
1911+
1912+
if (isDebugSection(*s))
1913+
return true;
1914+
if (auto *isec = dyn_cast<InputSection>(s))
1915+
if (InputSectionBase *rel = isec->getRelocatedSection())
1916+
if (isDebugSection(*rel))
1917+
return true;
1918+
1919+
return false;
19111920
});
19121921

19131922
// Now that the number of partitions is fixed, save a pointer to the main

lld/ELF/InputSection.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
441441
// See the comment in maybeReportUndefined for PPC64 .toc .
442442
auto *d = dyn_cast<Defined>(&sym);
443443
if (!d) {
444-
if (!sec->name.startswith(".debug") &&
445-
!sec->name.startswith(".zdebug") && sec->name != ".eh_frame" &&
444+
if (!isDebugSection(*sec) && sec->name != ".eh_frame" &&
446445
sec->name != ".gcc_except_table" && sec->name != ".toc") {
447446
uint32_t secIdx = cast<Undefined>(sym).discardedSecIdx;
448447
Elf_Shdr_Impl<ELFT> sec =

lld/ELF/InputSection.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,10 @@ class InputSection : public InputSectionBase {
357357
template <class ELFT> void copyShtGroup(uint8_t *buf);
358358
};
359359

360+
inline bool isDebugSection(const InputSectionBase &sec) {
361+
return sec.name.startswith(".debug") || sec.name.startswith(".zdebug");
362+
}
363+
360364
// The list of all input sections.
361365
extern std::vector<InputSectionBase *> inputSections;
362366

lld/test/ELF/emit-relocs-debug.s

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# REQUIRES: x86
2+
## Test --emit-relocs handles .debug*
3+
4+
# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
5+
# RUN: ld.lld --emit-relocs %t.o -o %t
6+
# RUN: llvm-readobj -r %t | FileCheck %s
7+
# RUN: ld.lld --emit-relocs --strip-debug %t.o -o %t.no
8+
# RUN: llvm-readobj -r %t.no | FileCheck --check-prefix=NO %s
9+
10+
# CHECK: Section {{.*}} .rela.debug_info {
11+
# CHECK-NEXT: R_X86_64_64 .text 0x0
12+
# CHECK-NEXT: }
13+
14+
# NO: Relocations [
15+
# NO-NEXT: ]
16+
17+
foo:
18+
19+
.section .debug_info
20+
.quad foo

0 commit comments

Comments
 (0)