Skip to content

Commit

Permalink
[nanoMIPS][LLD] .eh_frame section parsing changed
Browse files Browse the repository at this point in the history
Changed the way .eh_frame parsing is done for nanoMIPS, as they may
contain relocations referring to the size of the CIEs/FDEs. lld reads
.eh_frame sections using these sizes so it is necessary that the size
value is available at the time of .eh_frame section parsing.

It seems like integrated assembler for nanoMIPS is not resolving this
relocation at assembly time, but the gnu's assembler for nanoMIPS is
resolving it.
  • Loading branch information
AndrijaSyrmia committed Sep 27, 2024
1 parent 496ec0a commit 446214d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 0 deletions.
32 changes: 32 additions & 0 deletions lld/ELF/InputSection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1234,6 +1234,38 @@ void EhInputSection::split(ArrayRef<RelTy> rels) {
break;
}
uint64_t size = endian::read32<ELFT::TargetEndianness>(d.data());

if (config->emachine == EM_NANOMIPS) {
// nanoMIPS may have an unresolved relocation for size of CIE/FDE,
// calculate the value here, so proper values can be used
const uint64_t off = d.data() - content().data();
while (relI != rels.size() && rels[relI].r_offset < off)
++relI;

if (relI != rels.size()) {

// Resolving (composite) nanoMIPS relocation
const unsigned bits = sizeof(typename ELFT::uint) * 8;
uint64_t calculatedVal = getAddend<ELFT>(rels[relI]);
for (unsigned int relJ = relI;
relJ != rels.size() && rels[relJ].r_offset == off; ++relJ) {
const RelTy &rel = rels[relJ];
Symbol &sym = getFile<ELFT>()->getRelocTargetSym(rel);
RelType type = rel.getType(config->isMips64EL);
RelExpr expr = target->getRelExpr(type, sym, 0);
assert(expr != R_PC && expr != R_NANOMIPS_PAGE_PC &&
"PC relocs not expected for determining size of .eh_frame "
"entries");
calculatedVal = SignExtend64<bits>(
getRelocTargetVA(file, type, calculatedVal, 0, sym, expr));
}

// If the relocation exists, use its calculated value
// for the size
if (rels[relI].r_offset == off)
size = calculatedVal;
}
}
if (size == 0) // ZERO terminator
break;
uint32_t id = endian::read32<ELFT::TargetEndianness>(d.data() + 4);
Expand Down
20 changes: 20 additions & 0 deletions lld/test/ELF/nanomips-eh-frame-size-reloc.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# RUN: llvm-mc -filetype=obj -triple nanomips-elf -mcpu=i7200 %s -o %t.o
# RUN: ld.lld %t.o -o %t
# RUN: llvm-objdump -h %t | FileCheck %s

# CHECK: .eh_frame 0000002c

.linkrelax
.cfi_sections .eh_frame
.section .text, "ax", @progbits
.align 1
.globl _start
.ent _start

_start:
.cfi_startproc
nop
.cfi_endproc
.end _start
.size _start, .-_start

0 comments on commit 446214d

Please sign in to comment.